On your Pi, just run the following command;
wget -O - https://raw.githubusercontent.com/pjgpetecodes/dotnet5pi/master/install.sh | sudo bash
Here is the link to the author
A place to share
On your Pi, just run the following command;
wget -O - https://raw.githubusercontent.com/pjgpetecodes/dotnet5pi/master/install.sh | sudo bash
Here is the link to the author
My Raspberry Pi screen resolution being stuck at 800×600 with VNC access to a headless Raspberry PI with Raspberry Pi OS. I found that if I comment out the lines towards the end (as shown below) I was able to achieve a 1920×1080 resolution with my remote headless connection.
[pi4]
# Enable DRM VC4 V3D driver on top of the dispmanx display stack
#dtoverlay=vc4-fkms-v3d
#max_framebuffers=2
[all]
#dtoverlay=vc4-fkms-v3d
In my previous post, I introduced the SharpExt4 .Net library. In this post, I will show how to use SharpExt4 to access the Raspberry Pi SD card from Windows OS.
Note: If you want to access physical drive, you must run application in admin permission
static void Main(string[] args)
{
//Open Raspberry Pi SD card, see diskpart disk number
var disk = ExtDisk.Open(3);
//Get the file system, see diskpart partition number
var fs = ExtFileSystem.Open(disk.Parititions[1]);
//List all directories in root folder
foreach (var file in fs.GetDirectories("/", "*", SearchOption.TopDirectoryOnly))
{
Console.WriteLine(file);
}
}
Run the Sample project and see the result to list all the folders in Raspberry Pi root folder.
Follow my previous post: https://www.nickdu.com/?p=896
Open Ext4 file system.
//Get the file system
var fs = ExtFileSystem.Open(disk.Parititions[0]);
Sample code to open a file for read
//Open a file for read
var file = fs.OpenFile("/etc/shells", FileMode.Open, FileAccess.Read);
//Check the file length
var filelen = file.Length;
var buf = new byte[filelen];
//Read the file content
var count = file.Read(buf, 0, (int)filelen);
file.Close();
var content = Encoding.Default.GetString(buf);
Console.WriteLine(content);
Sample code for listing all files in a folder
//List all files in /etc folder
foreach (var file in fs.GetFiles("/etc", "*", SearchOption.AllDirectories))
{
Console.WriteLine(file);
}
Sample code for file creation
//Open a file for write
var file = fs.OpenFile("/etc/test", FileMode.Create, FileAccess.Write);
var hello = "Hello World";
var buf = Encoding.ASCII.GetBytes(hello);
//Write to file
file.Write(buf, 0, buf.Length);
file.Close();
Full ExtDisk APIs
public sealed class ExtDisk : IDisposable
{
public IList<Partition> Parititions { get; }
public Geometry Geometry { get; }
public ulong Capacity { get; }
public static ExtDisk Open(string imagePath);
public static ExtDisk Open(int DiskNumber);
public sealed override void Dispose();
public byte[] GetMasterBootRecord();
}
Full ExtFileSystem APIs
public sealed class ExtFileSystem : IDisposable
{
public static string MountPoint { get; }
public string Name { get; }
public string VolumeLabel { get; }
public bool CanWrite { get; }
public string Description { get; }
public static ExtFileSystem Open(Partition partition);
public void CopyFile(string sourceFile, string destinationFile, bool overwrite);
public void CreateDirectory(string path);
public void CreateHardLink(string target, string path);
public void CreateSymLink(string target, string path);
public void DeleteDirectory(string path);
public void DeleteFile(string path);
public bool DirectoryExists(string path);
public sealed override void Dispose();
public bool FileExists(string path);
public ValueType GetCreationTime(string path);
public string[] GetDirectories(string path, string searchPattern, SearchOption searchOption);
public ulong GetFileLength(string path);
public string[] GetFiles(string path, string searchPattern, SearchOption searchOption);
public DateTime GetLastAccessTime(string path);
public DateTime GetLastWriteTime(string path);
public uint GetMode(string path);
public Tuple<uint, uint> GetOwner(string path);
public void MoveDirectory(string sourceDirectoryName, string destinationDirectoryName);
public ExtFileStream OpenFile(string path, FileMode mode, FileAccess access);
public string ReadSymLink(string path);
public void RenameFile(string sourceFileName, string destFileName);
public void SetCreationTime(string path, DateTime newTime);
public void SetLastAccessTime(string path, DateTime newTime);
public void SetLastWriteTime(string path, DateTime newTime);
public void SetMode(string path, uint mode);
public void SetOwner(string path, uint uid, uint gid);
public sealed override string ToString();
public void Truncate(string path, ulong size);
}
Full ExtFileStream APIs
public class ExtFileStream : Stream
{
public ExtFileStream(ExtFileSystem fs, string path, FileMode mode, FileAccess access);
public override long Position { get; set; }
public override long Length { get; }
public override bool CanWrite { get; }
public override bool CanRead { get; }
public override bool CanSeek { get; }
public override void Close();
public override void Flush();
public override int Read(byte[] array, int offset, int count);
public override long Seek(long offset, SeekOrigin origin);
public override void SetLength(long value);
public override void Write(byte[] array, int offset, int count);
}
The full SharpExt4 library can be found at my GitHub.
Follow my last post SharpExt4, a .Net library, provides read/write Linux ext2/3/4 file system from Windows application.
The lwext4 is a great start point for me (thanks the author of lwext4), and it provides the core implementation of Linux ext2/3/4 filesystem.
What I need to do:
When creating this .Net library, I would like to access not only physical Linux disk directly, but also Linux disk image file.
SharpExt4 provides two open disk APIs:
//Open physical Linux disk
ExtDisk SharpExt4.ExtDisk.Open(int DiskNumber);
//Open Linux disk image file
ExtDisk SharpExt4.ExtDisk.Open(String imagePath);
Open Linux disk image allows developer to directly manipulate the saved Linux disk image file, e.g. Raspberry Pi OS image or Debian OS image. The saved Linux disk image must be raw format. This API doesn’t support Virtual Machine disk files (VHD, VDI, XVA, VMDK, etc).
This API also support open USB/Hard drive as physical disk by giving disk number. If you have a USB disk or hard drive formatted as ext2/3/4 file system, this API allows the developer to read/write directly.
To be continue…
Next post: https://www.nickdu.com/?p=912
As a day to day Windows user, it’s not easy to access Linux file system. Windows doesn’t natively supports Linux Extended file system access.
I have been working on Linux ARM IoT device, and it’s so annoying to be back and forth between Windows working PC and Linux development PC. I regularly need to burn/flash SD card, read/write file, remove/open directory in Linux device image.
These are the findings so far:
I decided to implement my own library. Finally, I found this, lwext4, a C library to provide ext2/3/4 filesystem for microcontrollers. According to the author, the library has some cool and unique features in microcontrollers world:
Lwext4 is an excellent choice for SD/MMC card, USB flash drive or any other wear leveled memory types. However it is not good for raw flash devices.
To be continue.
Next post https://www.nickdu.com/?p=896
I have been assigned a task to migrate Jira, our internal bug tracking system, to Azure DevOps cloud. There is a Jira plugin available, called TFS4JIAR, but it costs lots of money.
Here is my simple .Net C# code (if you want to use, you need modify to suit your own working environment)
Complete project can be found my github.
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace Jira2Azure
{
class Program
{
static string JIRAIssueQuery = "http://jiraserver:8080/rest/api/latest/search?jql={0}&fields=*all";
static string TFSBugUrl = "https://dev.azure.com/Test/SampleProject/_apis/wit/workitems/$Bug?api-version=6.0";
static string TFSAttachmentUrl = "https://dev.azure.com/Test/SampleProject/_apis/wit/attachments?fileName={0}&api-version=6.0";
static async Task<dynamic> JIRAGetIssues(string jql)
{
using (var client = new HttpClient())
{
//your Jira login credential
client.DefaultRequestHeaders.Add("Authorization", "Basic XXXXXXXXXX");
var msg = await client.GetStringAsync(string.Format(JIRAIssueQuery, jql));
dynamic issues = JsonConvert.DeserializeObject(msg);
return issues;
}
}
static async Task JIRA2TFS(string jql)
{
var issues = await JIRAGetIssues(jql);
foreach (var issue in issues.issues)
{
var tfs = ConvertJIRA2TFS(issue);
await TFSCreateIssue(tfs);
}
}
static async Task<dynamic> TFSUploadFile(string file, byte[] byteData)
{
file = Uri.EscapeUriString(file);
using (var client = new HttpClient())
{
//your Azure login credential
client.DefaultRequestHeaders.Add("Authorization", "Basic XXXXXXXXX");
using (var content = new ByteArrayContent(byteData))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
var msg = await client.PostAsync(string.Format(TFSAttachmentUrl, file), content);
var responseBody = msg.Content.ReadAsStringAsync().Result;
return JsonConvert.DeserializeObject(responseBody);
}
}
}
static byte[] JIRADownloadFile(dynamic url)
{
using (var client = new HttpClient())
{
//your Jira login credential
client.DefaultRequestHeaders.Add("Authorization", "Basic XXXXXXXX");
var content = client.GetByteArrayAsync((string)url).Result;
return content;
}
}
static string ConvertJIRA2TFS(dynamic issue)
{
//Additional JIRA link for documentation
string json = $"[{{\"op\": \"add\",\"path\": \"/relations/-\",\"value\": {{\"rel\": \"Hyperlink\",\"url\": \"{issue.self}\", \"attributes\": {{\"comment\": \"{issue.key}\"}}}}}},";
if (issue.fields.attachment != null)
{
foreach (var attach in issue.fields.attachment)
{
var content = JIRADownloadFile(attach.content);
var attchUrl = TFSUploadFile((string)attach.filename, content).Result;
var attachedJson = $"{{\"rel\":\"AttachedFile\",\"url\":\"{(string)attchUrl.url}\",\"attributes\":{{\"resourceSize\":{content.Length},\"name\":\"{(string)attach.filename}\"}}}}";
json += string.Format("{{\"op\":\"add\",\"path\":\"{0}\",\"from\": null,\"value\":{1}}},", "/relations/-", attachedJson);
}
}
string operation = "{{\"op\":\"add\",\"path\":\"{0}\",\"from\": null,\"value\":\"{1}\"}},";
//######### more field mapping
var fieldMapping = new Dictionary<string, dynamic>()
{
{ "/fields/System.Title",issue.fields.summary },
{ "/fields/Microsoft.VSTS.TCM.ReproSteps", issue.fields.description},
{ "/fields/Microsoft.VSTS.Common.Priority", issue.fields.priority.id},
};
foreach (var field in fieldMapping)
{
if (field.Value != null)
{
var str = ((string)field.Value).Replace("\"", "\\\"");
json += string.Format(operation, field.Key, str);
}
}
json = json.Replace("\r\n", "<br/>");
json = json.TrimEnd(',');
json += "]";
return json;
}
static async Task TFSCreateIssue(string json)
{
using (var client = new HttpClient())
{
//your Azure login credential
client.DefaultRequestHeaders.Add("Authorization", "Basic XXXXXXXXXX");
var content = new StringContent(json, Encoding.UTF8, "application/json-patch+json");
var msg = await client.PostAsync(TFSBugUrl, content);
}
}
static async Task Main(string[] args)
{
await JIRA2TFS("project = TAP");
}
}
}
I am currently working on a software project that involves connecting to a Java database (Apache Derby) via a .Net C# application. I googled a lot and nothing helps. Finally, I decided to find my own one, and managed to get it up running. Here is my solution to share:
Tools we need:
using java.lang;
using java.sql;
using System;
using org.apache.derby.jdbc;
namespace DerbyDB
{
class Program
{
static void Main(string[] args)
{
try
{
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
DriverManager.registerDriver(new EmbeddedDriver());
var derbyDBConnection = DriverManager.getConnection("jdbc:derby:C:/DerbyDB");
if (derbyDBConnection != null)
{
Statement st = derbyDBConnection.createStatement();
ResultSet rs = st.executeQuery("select * from eventlog");
while (rs.next())
{
Console.WriteLine(rs.getInt("ID"));
Console.WriteLine(rs.getTime("EVENT_DATE"));
Console.WriteLine(rs.getString("EVENT_MESSAGE"));
}
st.close();
derbyDBConnection.close();
}
}
catch (java.lang.Exception e)
{
Console.WriteLine(e);
}
}
}
}
I have a NAS, and it can be easily access from Raspberry Pi by using the following script:
mkdir nas
sudo mount -t cifs //lenovoez/documents /home/pi/nas/
This is a small script from https://www.cyberciti.biz/faq/linux-find-out-raspberry-pi-gpu-and-arm-cpu-temperature-command/ to monitor Raspberry Pi CPU&GPU temperature.
#!/bin/bash
# Script: my-pi-temp.sh
# Purpose: Display the ARM CPU and GPU temperature of Raspberry Pi
# Author: Vivek Gite <www.cyberciti.biz> under GPL v2.x+
# -------------------------------------------------------
cpu=$(</sys/class/thermal/thermal_zone0/temp)
echo "$(date) @ $(hostname)"
echo "-------------------------------------------"
echo "GPU => $(/opt/vc/bin/vcgencmd measure_temp)"
echo "CPU => $((cpu/1000))'C"
Save and close the file. Set permission:
chmod +x my-pi-temp.sh