Endpoint Community Project

Endpoint Community Project

I’ve been playing with Endpoint and I’m making a fun side project to see what the possibilities are. What better way to test things than to make something! I’m using a 480x272 touch display and Wi-Fi dongle.

STEP 1:
So, I decided to see what I could do in 100 lines of code or less! I thought it would be cool to just grab an image from a URL and display it on the screen. Pretty straight forward and easy.

using System.Device.Gpio;
using System.Device.Gpio.Drivers;
using SkiaSharp;
using GHIElectronics.Endpoint.Devices.Display;
using GHIElectronics.Endpoint.Core;
using GHIElectronics.Endpoint.Devices.Network;
using GHIElectronics.Endpoint.Devices.Rtc;

var rtc = new RtcController();
rtc.DateTime = new DateTime(2024, 2, 29, 7, 00, 45);

//Initialize Display
var backlightPort = EPM815.Gpio.Pin.PD14 / 16;
var backlightPin = EPM815.Gpio.Pin.PD14 % 16;
var backlightDriver = new LibGpiodDriver((int)backlightPort);
var backlightController = new GpioController(PinNumberingScheme.Logical, backlightDriver);
backlightController.OpenPin(backlightPin);
backlightController.SetPinMode(backlightPin, PinMode.Output);
backlightController.Write(backlightPin, PinValue.High);
var screenWidth = 480;
var screenHeight = 272;

var configuration = new FBDisplay.Configuration(){
    Clock = 10000,
    Width = 480,
    Hsync_start = 480 + 2,
    Hsync_end = 480 + 2 + 41,
    Htotal = 480 + 2 + 41 + 2,
    Height = 272,
    Vsync_start = 272 + 2,
    Vsync_end = 272 + 2 + 10,
    Vtotal = 272 + 2 + 10 + 2,
};
var fbDisplay = new FBDisplay(configuration);
var displayController = new DisplayController(fbDisplay);

//Initialize Network
bool NetworkReady = false;
var networkType = GHIElectronics.Endpoint.Devices.Network.NetworkInterfaceType.WiFi;

var networkSetting = new WiFiNetworkInterfaceSettings{
    Ssid = "YOUR SSID",
    Password = "YOUR PASSWORD",
    DhcpEnable = true,
};
var network = new NetworkController(networkType, networkSetting);

network.NetworkLinkConnectedChanged += (a, b) =>{
    if (b.Connected){
        Console.WriteLine("Connected");
        NetworkReady = true;
    }
    else{
        Console.WriteLine("Disconnected");
    }
};

network.NetworkAddressChanged += (a, b) =>{
    Console.WriteLine(string.Format("Address: {0}\n gateway: {1}\n DNS: {2}\n MAC: {3} ", b.Address, b.Gateway, b.Dns[0], b.MACAddress));
    NetworkReady = true;
};

network.Enable();

while (NetworkReady == false){
    Console.WriteLine("Waiting for connect");
    Thread.Sleep(250);
    
}

//SkiaSharp Initialization
SKBitmap bitmap = new SKBitmap(screenWidth, screenHeight, SKImageInfo.PlatformColorType, SKAlphaType.Premul);
bitmap.Erase(SKColors.Transparent);
SKBitmap webBitmap;

//Initialize Screen
using (var screen = new SKCanvas(bitmap)){
    // Load image URL.
    HttpClient httpClient = new HttpClient();

    string url = "https://www.ghielectronics.com/wp-content/uploads/2024/02//EndpointReleaseThumbnail.jpg";

    try{
        using (Stream stream = await httpClient.GetStreamAsync(url))
        using (MemoryStream memStream = new MemoryStream()){
            await stream.CopyToAsync(memStream);
            memStream.Seek(0, SeekOrigin.Begin);

            var info = new SKImageInfo(480, 272);
            webBitmap = SKBitmap.Decode(memStream,info);
            screen.DrawBitmap(webBitmap, 0, 0);

            var data = bitmap.Copy(SKColorType.Rgb565).Bytes;
            displayController.Flush(data);
            Thread.Sleep(1);
        };
    }
    catch{
    }
}

STEP 2:
Okay Cool, but what can I do with 200 lines of code?
I thought it would be awesome to use the Google Static Maps API. Building upon the idea of URL images I added Touch, to zoom in and out and buttons to change the map image type.

What I’ve done so far is in the Endpoint Samples Repo

STEP 3: Coming Soon!!!
Right now the Google Maps API is using a fixed location, GHI headquarters. Based on Long & Lat. I could add a keyboard and make it searchable by city or address…Awesome!!

Looks like my weekend is booked!

STEP 4: This is where I could use the communities’ help.
It would be nice if someone has a library using one of the many Mikro Bus GPS click modules available. The application could retrieve the map based on the device’s location. There are so MANY different types, does anyone have insight or experience on which would be best?

STEP 5: Google Map API…What would you add?
The API itself is FILLED with a ton of different options and neat features to do some seriously crazy things.

BASE CODE EXAMPLE
I added the base application to the Endpoint samples Repo, it would be nice to see what others can come up with…Oh and you’re not limited to just 200 lines… :wink:

4 Likes

For STEP 4:

GPS Module which can be used:
image
PID: MIKROE-1032

Code used:

using System.IO.Ports;
using System.Device.Gpio.Drivers;
using System.Device.Gpio;
using GHIElectronics.Endpoint.Core;
using System.Diagnostics;
using System.Text;

namespace testEndpointGPSSimple
{
    internal class Program
    {
        static byte[]? _lastSentence;
        static byte[] reader = new byte[512];
        static int idxReader = 0;
        static byte[] buffer = new byte[64];
        static bool started = false;

        static double _latitude;
        static double _longitude;
        static char _latitudeHemisphere;
        static char _longitudeOrientation;
        static void Main(string[] args)
        {
            Console.WriteLine("Start...");

            // Reset pin
            var pinNumber = EPM815.Gpio.Pin.PF4;
            var port = pinNumber / 16;
            var pin = pinNumber % 16;
            var gpioDriver = new LibGpiodDriver(port);
            var gpio = new GpioController(PinNumberingScheme.Logical, gpioDriver);
            gpio.OpenPin(pin);
            gpio.SetPinMode(pin, PinMode.Output);

            var _serial = new SerialPort
            {
                PortName = "/dev/ttySTM2",
                BaudRate = 9600,
                DataBits = 8,
                Parity = Parity.None,
                StopBits = StopBits.One,
            };
            EPM815.SerialPort.Initialize(EPM815.SerialPort.Uart3);

            // Reset GPS Click
            Console.WriteLine("Reset GPS");
            gpio.Write(pin, PinValue.High);
            Thread.Sleep(100);
            gpio.Write(pin, PinValue.Low);
            Thread.Sleep(200);
            gpio.Write(pin, PinValue.High);
            Thread.Sleep(100);

            _serial.Open();

            Console.WriteLine("Awaiting data...");
            while (true)
            {
                // Read data if any
                if (_serial.BytesToRead > 0)
                {
                    var received = _serial.Read(buffer, 0, buffer.Length);
                    ProcessBuffer(received);
                }
                // Check Parser state
                if (Parser.GLLSentence.Status == 'A')
                {
                    var latitude = Parser.GLLSentence.Latitude;
                    if (latitude != 0)
                    {
                        // Get Data
                        if (_latitude != latitude)
                        {
                            _latitude = latitude;
                            _latitudeHemisphere = Parser.GLLSentence.LatitudeHemisphere;
                            //Display Data
                            Debug.WriteLine("Lat: " + _latitude + _latitudeHemisphere);
                        }
                        if (_longitude != Parser.GLLSentence.Longitude)
                        {
                            _longitude = Parser.GLLSentence.Longitude;
                            _longitudeOrientation = Parser.GLLSentence.LongitudePosition;
                            //Display Data
                            Debug.WriteLine("Lon: " + _longitude + _longitudeOrientation);
                        }

                    }
                }
                Thread.Sleep(20);
            }
        }

        private static void ProcessBuffer(int received)
        {
            for (int i = 0; i < received; i++)
            {
                var ch = Encoding.UTF8.GetString(buffer, i, 1);
                if (!started)
                    if (ch == "$")
                    {
                        idxReader = 0;
                        reader[idxReader] = buffer[i];
                        started = true;
                        idxReader++;
                    }
                    else
                    {
                        // Discard byte
                    }
                else
                {
                    if (ch == "$") // Already started, so restart
                    {
                        idxReader = 0;
                        reader[idxReader] = buffer[i];
                        started = true;
                        idxReader++;
                    }
                    else if (ch == "\r")
                    { // End of sentence
                        started = false;
                        // Get sentence from reader idx 0 to idxReader
                        _lastSentence = new byte[idxReader];
                        Array.Copy(reader, _lastSentence, idxReader);
                        ProcessSentence(_lastSentence);

                    }
                    else
                    { // Keep copying
                        reader[idxReader] = buffer[i];
                        idxReader++;

                    }

                }
            }
        }

        private static void ProcessSentence(byte[] lastSentence)
        {
            //            Debug.WriteLine(Encoding.UTF8.GetString(lastSentence));
            Parser.Parse(lastSentence);
        }
    }
}```
1 Like

yea, I heard those Ublox ones are really good.

2 Likes