Antarmuka Port Serial dengan C++

Gunakan Class Serial berikut:

//File: Serial.h
#ifndef SERIALCLASS_H_INCLUDED
#define SERIALCLASS_H_INCLUDED

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

class Serial
{
    private:
        //Serial comm handler
        HANDLE hSerial;
        //Connection status
        bool connected;
        //Get various information about the connection
        COMSTAT status;
        //Keep track of last error
        DWORD errors;

    public:
        //Initialize Serial communication with the given COM port
        Serial(char *portName);
        //Close the connection
        ~Serial();
        //Read data in a buffer, if nbChar is greater than the
        //maximum number of bytes available, it will return only the
        //bytes available. The function return -1 when nothing could
        //be read, the number of bytes actually read.
        int ReadData(char *buffer, unsigned int nbChar);
        //Writes data from a buffer through the Serial connection
        //return true on success.
        bool WriteData(char *buffer, unsigned int nbChar);
        //Check if we are actually connected
        bool IsConnected();


};

#endif // SERIALCLASS_H_INCLUDED

//File: Serial.cpp
#include "Serial.h"

Serial::Serial(char *portName)
{
    //We're not yet connected
    this->connected = false;

    //Try to connect to the given port throuh CreateFile
 #if _MSC_VER && !__INTEL_COMPILER
    const size_t cSize = strlen(portName) + 1;
    wchar_t* wc = new wchar_t[cSize];
    mbstowcs_s(NULL, wc, cSize, portName, cSize);
    this->hSerial = CreateFile(wc,
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
#else
    //Try to connect to the given port throuh CreateFile
    this->hSerial = CreateFile(portName,
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
#endif

    //Check if the connection was successfull
    if(this->hSerial==INVALID_HANDLE_VALUE)
    {
        //If not success full display an Error
        if(GetLastError()==ERROR_FILE_NOT_FOUND){

            //Print Error if neccessary
            printf("ERROR: Handle was not attached. Reason: %s not available.\n", portName);

        }
        else
        {
            printf("ERROR!!!");
        }
    }
    else
    {
        //If connected we try to set the comm parameters
        DCB dcbSerialParams = {0};

        //Try to get the current
        if (!GetCommState(this->hSerial, &dcbSerialParams))
        {
            //If impossible, show an error
            printf("failed to get current serial parameters!");
        }
        else
        {
            //Define serial connection parameters for the arduino board
            dcbSerialParams.BaudRate=CBR_9600;
            dcbSerialParams.ByteSize=8;
            dcbSerialParams.StopBits=ONESTOPBIT;
            dcbSerialParams.Parity=NOPARITY;
            //Setting the DTR to Control_Enable ensures that the Arduino is properly
            //reset upon establishing a connection
            dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;

             //Set the parameters and check for their proper application
             if(!SetCommState(hSerial, &dcbSerialParams))
             {
                printf("ALERT: Could not set Serial Port parameters");
             }
             else
             {
                 //If everything went fine we're connected
                 this->connected = true;
                 //Flush any remaining characters in the buffers
                 PurgeComm(this->hSerial, PURGE_RXCLEAR | PURGE_TXCLEAR);
                 //We wait 2s as the arduino board will be reseting
                 Sleep(2000);
             }
        }
    }

}

Serial::~Serial()
{
    //Check if we are connected before trying to disconnect
    if(this->connected)
    {
        //We're no longer connected
        this->connected = false;
        //Close the serial handler
        CloseHandle(this->hSerial);
    }
}

int Serial::ReadData(char *buffer, unsigned int nbChar)
{
    //Number of bytes we'll have read
    DWORD bytesRead;
    //Number of bytes we'll really ask to read
    unsigned int toRead;

    //Use the ClearCommError function to get status info on the Serial port
    ClearCommError(this->hSerial, &this->errors, &this->status);

    //Check if there is something to read
    if(this->status.cbInQue>0)
    {
        //If there is we check if there is enough data to read the required number
        //of characters, if not we'll read only the available characters to prevent
        //locking of the application.
        if(this->status.cbInQue>nbChar)
        {
            toRead = nbChar;
        }
        else
        {
            toRead = this->status.cbInQue;
        }

        //Try to read the require number of chars, and return the number of read bytes on success
        if(ReadFile(this->hSerial, buffer, toRead, &bytesRead, NULL) && bytesRead != 0)
        {
            return bytesRead;
        }

    }

    //If nothing has been read, or that an error was detected return -1
    return -1;

}


bool Serial::WriteData(char *buffer, unsigned int nbChar)
{
    DWORD bytesSend;

    //Try to write the buffer on the Serial port
    if(!WriteFile(this->hSerial, (void *)buffer, nbChar, &bytesSend, 0))
    {
        //In case it don't work get comm error and return false
        ClearCommError(this->hSerial, &this->errors, &this->status);

        return false;
    }
    else
        return true;
}

bool Serial::IsConnected()
{
    //Simply return the connection status
    return this->connected;
}


Berikut contoh koneksi pengiriman data

#include <iostream>
#include "windows.h"
#include "Serial.h"

#include <thread>
#include <chrono>

using namespace std;

void delay(int ms){
    std::this_thread::sleep_for (std::chrono::milliseconds(ms));
}

int main(int argc, char** argv) {

    char alamatPort[] = "\\\\.\\COM7";
    Serial* s = new Serial(alamatPort);

	char dataOn[256] = "on1\n"; //"Nyala!";
	char dataOff[256] = "off0\n"; //"mati!";

	cout<<"isikan angka 1 untuk menyalakan, atau 0 untuk mematikan"<<endl;


	int jawab;
	do{
        cin>>jawab;;

        if(jawab==0)
            s->WriteData(dataOff, sizeof(dataOff));
        if(jawab==1)
            s->WriteData(dataOn, sizeof(dataOn));
        if(jawab==2)
            for(int a=0;a<5;a++){
                s->WriteData(dataOn, sizeof(dataOn));
                delay(500);
                s->WriteData(dataOff, sizeof(dataOff));
                delay(500);
            }
	}while(jawab<3);

	return 0;
}

Berikut contoh untuk mengirim dan menerima data

#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include "Serial.h" // Library described above
#include <string>


/* run this program using the console pauser or add your own getch, system("pause") or input loop */
char alamatPort[] = "\\\\.\\COM7";
Serial* SP = new Serial(alamatPort);    // adjust as needed

void* baca(void* data)
{

    char incomingData[256] = "";            // don't forget to pre-allocate memory
    //printf("%s\n",incomingData);
    int dataLength = 256;
    int readResult = 0;


    while (SP->IsConnected())
    {
        readResult = SP->ReadData(incomingData, dataLength);
        if (readResult > 0) {
            printf("%s\n", incomingData);
        }
        //printf("Bytes read: (-1 means no data available) %i\n",readResult);

        //std::string test(incomingData);

        //printf("%s",incomingData);
        //test = "";

        Sleep(500);
    }
    return NULL;
}

void* tulis(void* data)
{
    while (SP->IsConnected())
    {
        char outgoingData[256] = "";
        char keluar[256] = "keluar";
        int dataLength = sizeof(outgoingData);        // don't forget to pre-allocate memory
        scanf_s("%255s", outgoingData, dataLength);

        if (outgoingData != "")
        {
            if (strcmp(outgoingData, "OK") == 0) {
                printf("Pengiriman selesai\n");
                return NULL;

            }
            if (SP->WriteData(outgoingData, dataLength))
            {
                printf("Data send:%s\n", outgoingData);
            }
        }

        Sleep(500);
    }
    // do stuff...
    return NULL;
}

#if _MSC_VER && !__INTEL_COMPILER
#include <thread>

int main(int argc, char** argv) {
    printf("Welcome to the serial test app!\n\n");
    if (SP->IsConnected())
        printf("Serial sudah terhubung\n");
    int status;
    std::thread thrd_1(baca,(void*)0);
    std::thread thrd_2(tulis, (void*)0);

    thrd_1.join();
    thrd_2.join();

}
#else
// thread example
#include <pthread.h>

int main(int argc, char** argv) {
    printf("Welcome to the serial test app!\n\n");
    if (SP->IsConnected())
        printf("Serial sudah terhubung\n");

    pthread_t thrd_1;
    pthread_t thrd_2;
    int status;

    pthread_create(&thrd_1, NULL, baca, (void*)0);
    pthread_create(&thrd_2, NULL, tulis, (void*)0);

    pthread_join(thrd_1, (void**)&status);
    pthread_join(thrd_2, (void**)&status);

    printf("Terima kasih");

    return 0;
}
#endif

PTZ Control on ONVIF Standard in C#

Looking at highly price Camera SDK to handle ONVIF Standard, I decided to build some code to control PTZ camera movement using C#.

It it a nice tutorial video by Onvif Channel. That video describes basic step to make a C# project on visual studio. Unfortunately, I can’t get it work for my camera. I’m having YooSee camera GW-1113 which is already support PTZ Control.

There is another tutorial in CodeProject to use PTZ Control. My code is always get a closed connection message from the camera. Both using password or nor, it alway failed. Next, I got nice tool to cek my Onvif Camera. It can detect camera’s IP, port, display video stream and controlling camera using PTZ. You can get it here https://sourceforge.net/projects/onvifdm/ Afterward, I got IP, Port, and service.

With correct IP, Password, port and service address, it still error on getProfiles() command. I inisiate to find tool to debug Onvif request. I grab this tool in this forum https://support.yooseecamera.com/threads/233/ Nice step by step tutorial with pictures. I made my dummy service and dump post header request and then save it into textfile. Here is PHP code i got from // https://gist.github.com/magnetikonline/650e30e485c0f91f2f40 to dump request. I save it on http://localhost:5000/onvif/device_service/index.php

<?php

class DumpHTTPRequestToFile {

	public function execute($targetFile) {

		$data = sprintf(
			"%s %s %s\n\nHTTP headers:\n",
			$_SERVER['REQUEST_METHOD'],
			$_SERVER['REQUEST_URI'],
			$_SERVER['SERVER_PROTOCOL']
		);

		foreach ($this->getHeaderList() as $name => $value) {
			$data .= $name . ': ' . $value . "\n";
		}

		$data .= "\nRequest body:\n";

		file_put_contents(
			$targetFile,
			$data . file_get_contents('php://input') . "\n"
		);

		echo("Done!\n\n");
	}

	private function getHeaderList() {

		$headerList = [];
		foreach ($_SERVER as $name => $value) {
			if (preg_match('/^HTTP_/',$name)) {
				// convert HTTP_HEADER_NAME to Header-Name
				$name = strtr(substr($name,5),'_',' ');
				$name = ucwords(strtolower($name));
				$name = strtr($name,' ','-');

				// add to list
				$headerList[$name] = $value;
			}
		}

		return $headerList;
	}
}


(new DumpHTTPRequestToFile)->execute('./dumprequest.txt');
exit();

And here are resutl I got from C# and Device Test Tool

POST /onvif/device_service/index.php HTTP/1.1

HTTP headers:
Host: localhost
Expect: 100-continue
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

Request body:
<?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><GetCapabilities xmlns="http://www.onvif.org/ver10/device/wsdl" /></s:Body></s:Envelope>


POST /onvif/device_service/index.php HTTP/1.1

HTTP headers:
Host: localhost
Accept: */*

Request body:
<?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><GetCapabilities xmlns="http://www.onvif.org/ver10/device/wsdl" /></s:Body></s:Envelope>


Above was C# request, while next into it was Tool request You can see that the difference is only at HTTP headers section. Thus, I have to remove Expect:100-continue , gzip compression and Keep-Alive Connection (oprional). As well as add an Accept type.

            try
            {
                var messageElement = new TextMessageEncodingBindingElement()
                {
                    MessageVersion = MessageVersion.CreateVersion(
                      EnvelopeVersion.Soap12, AddressingVersion.None)
                };

                HttpTransportBindingElement httpBinding = new HttpTransportBindingElement()
                {
                    AuthenticationScheme = AuthenticationSchemes.Digest

                };
                //remove compression
                httpBinding.DecompressionEnabled = false;
                // remove keep alive
                httpBinding.KeepAliveEnabled = false;


                CustomBinding bind = new CustomBinding(messageElement, httpBinding);
                // Remove Expect
                ServicePoint servicePoint =
                    ServicePointManager.FindServicePoint(service_uri);
                servicePoint.Expect100Continue = false;

                if (searchServiceUri)
                {
                    // now execute some service operation 
                    Device.DeviceClient device = new Device.DeviceClient(bind,
                      new EndpointAddress(service_uri));
                    device.ClientCredentials.HttpDigest.AllowedImpersonationLevel =
                      System.Security.Principal.TokenImpersonationLevel.Impersonation;
                    device.ClientCredentials.HttpDigest.ClientCredential.UserName = userName;
                    device.ClientCredentials.HttpDigest.ClientCredential.Password = password;

                    Device.Capabilities cap = device.GetCapabilities(null);

                }

Later I got nice php script to controlling PTZ at https://github.com/sergejey/majordomo-onvif/blob/master/modules/onvif/class.ponvif.php

Menggunakan SharpDX untuk Joystick

Tambahkan paket NuGet SharpDX.DirectInput

using System;
using System.Threading;

using SharpDX.DirectInput;

namespace PanelRosita
{

    public enum ButtonState : int
    {
        Idle = -1,
        Released = 0,
        Pressed = 128
    }

    public class JoystickThread
    {
        public Thread thr;
        public bool conditionToExitReceived = false;
        public bool isJoystickDetected = false;

        public JoystickThread(string name)
        {

            // detecting joystick
            // Initialize DirectInput
            var directInput = new DirectInput();

            // Find a Joystick Guid
            var joystickGuid = Guid.Empty;

            var devInstance = new DeviceInstance();

            foreach (var deviceInstance in directInput.GetDevices(DeviceType.Gamepad,
                        DeviceEnumerationFlags.AllDevices))
            {
                joystickGuid = deviceInstance.InstanceGuid;
                devInstance = deviceInstance;
            }

            // If Gamepad not found, look for a Joystick
            if (joystickGuid == Guid.Empty)
                foreach (var deviceInstance in directInput.GetDevices(DeviceType.Joystick,
                        DeviceEnumerationFlags.AllDevices))
                {
                    joystickGuid = deviceInstance.InstanceGuid;
                    devInstance = deviceInstance;
                }

            // If Joystick not found, throws an error
            if (joystickGuid == Guid.Empty)
            {
                Console.WriteLine("No joystick/Gamepad found.");
                conditionToExitReceived = true;
                throw new Exception("No joystick/Gamepad found.");
            }

            // Instantiate the joystick
            var joystick = new Joystick(directInput, joystickGuid);
            Console.WriteLine("Found Joystick/Gamepad with GUID: {0}", joystickGuid);


            thr = new Thread(() => RunThread(joystick) );
            thr.Name = name;
            thr.Start();
            isJoystickDetected = true;
        }

        // Enetring point for thread 
        void RunThread(Joystick joystick)
        {


            // Query all suported ForceFeedback effects
            Console.WriteLine("Effect:");
            var allEffects = joystick.GetEffects();
            foreach (var effectInfo in allEffects)
                Console.WriteLine("Effect available {0}", effectInfo.Name);

            // Set BufferSize in order to use buffered data.
            joystick.Properties.BufferSize = 128;

            // Acquire the joystick
            joystick.Acquire();

            try
            {
                while (true)
                {
                    if (conditionToExitReceived) // what im waiting for...
                    {
                        Console.WriteLine("Thread is finished");
                        break;
                    }
                    Thread.Sleep(10); // wait 1 second for something to happen.
                    doStuff(ref joystick);
                }
                //perform cleanup if there is any...

            }
            catch (ThreadAbortException ex)
            {
                Console.WriteLine("Thread " + thr.Name + " is aborted and the code is "
                                                 + ex.ExceptionState);
            }
        }

        private void doStuff(ref Joystick joystick)
        {

            try
            {
                joystick.Poll();


                var datas = joystick.GetBufferedData();
                foreach (var state in datas)
                {
                    JoystickButtonPressedEventArgs args = new JoystickButtonPressedEventArgs();
                    JoystickButtonPOVEventArgs povargs = new JoystickButtonPOVEventArgs();
                    args.Value = (ButtonState)state.Value;
                    args.ButtonOffset = state.RawOffset;
                    args.TimeStamp = DateTime.Now;

                    povargs.Value = state.Value;

                    if (state.Offset == JoystickOffset.Buttons0)
                    {
                        OnJoystickButton0(args);
                    }
                    if (state.Offset == JoystickOffset.PointOfViewControllers0)
                    {
                        OnJoystickPointOfViewControllers0(povargs);
                    }

                    if (state.Offset != JoystickOffset.X && state.Offset != JoystickOffset.Y && state.Offset != JoystickOffset.RotationZ)
                    {
                        Console.WriteLine("Joystick: " + state);
                    }
                }
            }
            catch (Exception ee)
            {
                OnJoystickDisconnected(ee.Message);
                conditionToExitReceived = true;
                Console.WriteLine("Joystick: " + ee);
                isJoystickDetected = false;
            }
        }

        public class JoystickButtonPressedEventArgs : EventArgs
        {
            public ButtonState Value { get; set; }
            public int ButtonOffset { get; set; }
            public DateTime TimeStamp { get; set; }
        }
        public class JoystickButtonPOVEventArgs : EventArgs
        {
            public int Value { get; set; }
            public int ButtonOffset { get; set; }
            public DateTime TimeStamp { get; set; }
        }

        public event EventHandler<String> OnDisconnected0;
        protected virtual void OnJoystickDisconnected(String e)
        {
            EventHandler<String> handler = OnDisconnected0;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        public event EventHandler<JoystickButtonPressedEventArgs> OnButton0;
        protected virtual void OnJoystickButton0(JoystickButtonPressedEventArgs e)
        {
            EventHandler<JoystickButtonPressedEventArgs> handler = OnButton0;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<JoystickButtonPOVEventArgs> OnPointOfViewControllers0;
        protected virtual void OnJoystickPointOfViewControllers0(JoystickButtonPOVEventArgs e)
        {
            EventHandler<JoystickButtonPOVEventArgs> handler = OnPointOfViewControllers0;
            if (handler != null)
            {
                handler(this, e);
            }
        }




    }
}


Penggunaan

       JoystickThread jt;
       private void Form1_Load(object sender, EventArgs e)
        {
            ConnectingToJoystick(FindingJoystick());
        }


        private void ErrorBox(string v)
        {
            MessageBox.Show(v,Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
        }

        private void ConnectingToJoystick(bool joystickDetected)
        {
            if (joystickDetected)
            {
                try
                {
                    jt = new JoystickThread("JoyStick");
                    if (jt.isJoystickDetected)
                    {
                        //add all event here
                        jt.OnButton0 += Jt_OnButton0;
                        jt.OnDisconnected0 += Jt_OnDisconnected0;
                        jt.OnPointOfViewControllers0 += Jt_OnPointOfViewControllers0;
                        jt.isJoystickDetected = true;
                    }
                    else {
                        ErrorBox("Joystick tidak terdeteksi atau tidak kompatibel");
                    }
                }
                catch (Exception ee)
                {
                    ErrorBox("Joystick:" + ee.Message);
                }
            }
        }


        private static bool FindingJoystick()
        {
            Boolean joystickDetected = false;

            // Initialize DirectInput
            var directInput = new DirectInput();

            while (!joystickDetected)
            {

                var devInstance = new DeviceInstance();

                // Find a Joystick Guid
                var joystickGuid = Guid.Empty;

                foreach (var deviceInstance in directInput.GetDevices(DeviceType.Gamepad,
                            DeviceEnumerationFlags.AllDevices))
                {
                    joystickGuid = deviceInstance.InstanceGuid;
                    devInstance = deviceInstance;
                }

                // If Gamepad not found, look for a Joystick
                if (joystickGuid == Guid.Empty)
                    foreach (var deviceInstance in directInput.GetDevices(DeviceType.Joystick,
                            DeviceEnumerationFlags.AllDevices))
                    {
                        joystickGuid = deviceInstance.InstanceGuid;
                        devInstance = deviceInstance;
                    }

                // If Joystick not found, throws an error
                if (joystickGuid == Guid.Empty)
                {
                    Console.WriteLine("No joystick/Gamepad found.");
                    DialogResult rst = MessageBox.Show("Joystick tidak ditemukan atau tidak terhubung. Hubungkan joystick dan klik RETRY, atau klik CANCEL untuk tidak menggunakan joystick.", Application.ProductName, MessageBoxButtons.RetryCancel, MessageBoxIcon.Warning);
                    if (rst == DialogResult.Cancel)
                    {
                        return joystickDetected;
                    }
                }
                else
                {
                    joystickDetected = true;
                }
            }
            return joystickDetected;
        }

       private void Jt_OnDisconnected0(object sender, string e)
        {
            //stop robot

            //Finding joystick
            DialogResult rst = MessageBox.Show("No Joystick found. Please Connect the joystick.", Application.ProductName, MessageBoxButtons.RetryCancel, MessageBoxIcon.Warning);
            if (rst == DialogResult.Retry)
            {
                ConnectingToJoystick(FindingJoystick());
            }
        }

        private void Jt_OnPointOfViewControllers0(object sender, JoystickThread.JoystickButtonPOVEventArgs e)
        {
            MessageBox.Show("POV value: "+e.Value.ToString());
        }

        private void Jt_OnButton0(object sender, JoystickThread.JoystickButtonPressedEventArgs e)
        {
            String state = "";
            if (e.Value == ButtonState.Pressed)
                state = "Pencet";
            else
                state = "Lepas";

            //Invoke state to button1
            //button1.Invoke(new Action(() => button1.Text = state));

        }


        //Add event on FormClosing to release object
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (jt != null)
            {
                //force to abort
                //jt.thr.Abort("aborted from Main");

                //ask thread to exit polling
                jt.conditionToExitReceived = true;
                
                // Waiting for a thread to terminate. 
                jt.thr.Join();
                Console.WriteLine(jt.thr.Name + " is terminate");
            }
        }

Tutorial CefSharp

Buka Menu: Project -> Manage NuGet Package

Pasang CefSharp.Winform, CefSharp.Common

Ganti Target Net 4.5.2 keatas dan platform configuration (x86, x64 or AnyCPU)

Jika menggunakan AnyCPU, bagian Project > Your Project Properties > Build centang bagian Prefer-32bit. Jika menggunakan x64, buatlah Configurasi untuk x64 (Silahkan googling)

Perbaiki file .csproj

Tambahkan sebelum tag </PropertyGroup>

<CefSharpAnyCpuSupport>true</CefSharpAnyCpuSupport>

Configuration Error

jika menemukan: Please check to make sure that you have specified a valid combination of Configuration and Platform for this project. Maka buka

Klik kanan Project > Properties > Build lalu cut pada bagian Output Path. Selanjutnya Build project lalu paste lagi di tempat semula. Selanjutnya silahkan coba rebuild lagi.

program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

using CefSharp;
using CefSharp.WinForms;
using System.IO;

namespace WindowsFormsApplication1
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Cef.EnableHighDPISupport();

            var settings = new CefSettings()
            {
                //By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
                CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache")
            };
            //Example of setting a command line argument
            //Enables WebRTC
            settings.CefCommandLineArgs.Add("enable-media-stream");

            //Perform dependency check to make sure all relevant resources are in our output directory.
            Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using CefSharp;
using CefSharp.WinForms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public ChromiumWebBrowser chromeBrowser;

        public Form1()
        {
            InitializeComponent();
            InitializeChromium();
        }

        public void InitializeChromium()
        {
            // Create a browser component
            //chromeBrowser = new ChromiumWebBrowser("http://admin:@192.168.43.10/video.cgi");
            chromeBrowser = new ChromiumWebBrowser("http://localhost:8001/camera/mjpeg");
            // Add it to the form and fill it to the form window.
            panel1.Controls.Add(chromeBrowser);
            chromeBrowser.Dock = DockStyle.Fill;

            //Wait for the page to finish loading (all resources will have been loaded, rendering is likely still happening)
            chromeBrowser.LoadingStateChanged += (sender, args) =>
            {
                //Wait for the Page to finish loading
                Console.WriteLine("Loading State Changed GoBack {0} GoForward {1} CanReload {2} IsLoading {3}", args.CanGoBack, args.CanGoForward, args.CanReload, args.IsLoading);
                if (args.CanReload && !args.IsLoading)
                {
                    //chromeBrowser.Reload();
                }
            };

            chromeBrowser.IsBrowserInitializedChanged += OnIsBrowserInitializedChanged;

            //Wait for the MainFrame to finish loading
            chromeBrowser.FrameLoadEnd += (sender, args) =>
            {
                //Wait for the MainFrame to finish loading
//                if (args.Frame.IsMain)
                {
                    Console.WriteLine("MainFrame finished loading Status code {0}", args.HttpStatusCode);
                    if (args.HttpStatusCode == 200)
                    {
                        //finished, OK, streaming end
                        chromeBrowser.Reload();
                    }
                    if (args.HttpStatusCode == -101)
                    {
                        //finished, OK, streaming shut down
                        chromeBrowser.Reload();
                    }
                    if (args.HttpStatusCode == 0)
                    {
                        //The client request wasn't successful.
                        chromeBrowser.Reload();
                    }
                }
            };

        }

        private void ChromeBrowser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)
        {
            Console.WriteLine("end");
        }

        private void OnLoadingStateChanged(object sender, LoadingStateChangedEventArgs e)
        {
            Console.WriteLine(chromeBrowser.IsLoading);
        }

        private void OnIsBrowserInitializedChanged(object sender, EventArgs e)
        {
            var b = ((ChromiumWebBrowser)sender);

            this.InvokeOnUiThreadIfRequired(() => b.Focus());
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string url = textBox1.Text;
            if (Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute))
            {
                chromeBrowser.Load(url);
            }
        }
    }


    public static class ControlExtensions
    {
        /// <summary>
        /// Executes the Action asynchronously on the UI thread, does not block execution on the calling thread.
        /// </summary>
        /// <param name="control">the control for which the update is required</param>
        /// <param name="action">action to be performed on the control</param>
        public static void InvokeOnUiThreadIfRequired(this Control control, Action action)
        {
            //If you are planning on using a similar function in your own code then please be sure to
            //have a quick read over https://stackoverflow.com/questions/1874728/avoid-calling-invoke-when-the-control-is-disposed
            //No action
            if (control.Disposing || control.IsDisposed || !control.IsHandleCreated)
            {
                return;
            }

            if (control.InvokeRequired)
            {
                control.BeginInvoke(action);
            }
            else
            {
                action.Invoke();
            }
        }
    }
}

sumber: https://ourcodeworld.com/articles/read/173/how-to-use-cefsharp-chromium-embedded-framework-csharp-in-a-winforms-application

Printer POS USB menggunakan PHP

<?php  
$tmpdir = sys_get_temp_dir();   # ambil direktori temporary untuk simpan file.
$file =  tempnam($tmpdir, 'ctk');  # nama file temporary yang akan dicetak (Windows, samba)

$handle = fopen($file, 'w');


//Printer parameter (ESC POS Command)
$initialized = chr(27).chr(64);

$justify = Chr(27) . Chr(97);
$left = Chr(0); $center = Chr(1);$right = Chr(2);

$fontwidth = Chr(27).Chr(87);
$doublewidth = Chr(1); $normalwidth = Chr(0);

$LF = Chr(10);

//Start making data
$Data  = $initialized;
$Data .= $fontwidth.$doublewidth;
$Data .= $justify.$center;
$Data .= "NAMA TOKO"."\n";
$Data .= $fontwidth.$normalwidth;
$Data .= "Alamat Toko"."\n";
$Data .= $LF.$LF;

//Write data to temporary file
fwrite($handle, $Data);
fclose($handle);

//WIN: send temporary file to nerwork shared printer (share your printer)
//LINUX: send data directly to device
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'){ //Win
    copy($file, "//localhost/POS-58");  # Shared Printer as POS-58
}else if (strtoupper(substr(PHP_OS, 0, 3)) === 'LIN'){ //Linux    
    $device = "/dev/usb/lp0";           # Print at lp0, find it using lsusb! Use udev for managing user access
    if (is_writable($device)) {
        $fp =fopen($device, "w");
        if($fp) {
            fwrite($fp, $Data);
            fclose($fp);
        }
    }
}

unlink($file);
//echo $Data;

?>

Cara mencetak ke printer POS menggunakan PHP. Skrip ini mencontohkan jika menggunakan Windows maupun Linux.

Untuk menggunakan Windows maupun Linux, printer dibuat menjadi akses bersama (shared printer) terlebih dahulu lalu beri nama, misalnya: POS-58. Pastikan bisa diakses di //ALAMAT_IP/NAMA_PRINTER. Untuk skrip ini, menggunakan //localhost/POS-58 Untuk di Windows, buka di Control Panel, pastikan printer yang di-share sudah tersedia dan online.

Sedangkan jika menggunakan Linux, cari nama device dengan perintah:

ls /dev/usb

alamat device printer akan diawali dengan lpx, dimana x bisa 0,1,2 atau angka yang lain. Bagaimana bisa memastikan mana alamat device yang benar? gunakan perintah berikut:

echo "Test Printer" >> /dev/usb/lp0 

Jika printer bisa mencetak, berarti alamat printer adalah benar, yaitu /dev/usb/lp0 jika salah ganti angka 0 dengan angka 1 atau 2 atau angka lain hingga printer bisa mencetak. Pada skrip ini, alamat device perinter adalah /dev/usb/lp0

Install Font di NSIS

Unduh file berikut, taruh script header .nsh di folder include, dan library .dll di folder plugins (atau plugins/x86_ansi) jika menggunakan Windows 64bit

https://nsis.sourceforge.io/mediawiki/images/7/78/FontName-0.7.zip (installer, pindah FileName.dll ke x86_ansi jika OS 64bit) atau unduh https://file.io/yBr4UoFl

!include FontReg.nsh
!include FontName.nsh
!include WinMessages.nsh

StrCpy $FONT_DIR $FONTS
!insertmacro InstallTTFFont "SiapCetak\settings\fonts\SR.ttf"
SendMessage ${HWND_BROADCAST} ${WM_FONTCHANGE} 0 0 /TIMEOUT=5000

Jika menggunakan GDI

!include WinMessages.nsh

System::Call "GDI32::AddFontResourceA(t) i ('SR.ttf') .s"
Pop $0
# $0 is zero if the function failed
SendMessage ${HWND_BROADCAST} ${WM_FONTCHANGE} 0 0 /TIMEOUT=5000

Mencari lokasi MyDocument

Function "GetMyDocs"
  ReadRegStr $0 HKCU \
             "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" \
             Personal
FunctionEnd

Call "GetMyDocs"
$MyDocs = $0

Memprogram 24LC64 dengan Port Serial

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace _24LC64
{
    /// 
<summary>
    /// Pin 3 (TX)  --          -- CS
    /// pin 4 (DTR) -- SCL      -- SCK
    /// Pin 6 (DSR) -- SDA IN   -- 
    /// Pin 7 (RTS) -- SDA OUT  -- MOSI (DO)
    /// Pin 8 (CTS) --          -- MISO (DI)
    /// </summary>


    public partial class Form1 : Form
    {
        public const bool H = true, L = false;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            serialPort1.BaudRate = 9600;
            serialPort1.PortName = textBox1.Text;
            serialPort1.Open();

            //serialPort1.DtrEnable = true;
            //serialPort1.RtsEnable = true;

            //perintah Write
            StartBit();
            kirim(0xA0);
            bit(1); //ACK
            
            //Alamat memory (0x001)
            //0x00 
            kirim(0x00);
            bit(1); //ACK
            //0x01
            kirim(0x01);
            bit(1); //ACK

            //Data (0x33)
            //kirim(0x33);
            byte[] data = StringToByteArray(textBox2.Text);
            kirim(data[0]);
            bit(1); //ACK
            
            StopBit();


            serialPort1.Close();

        }
        void kirim(int byteData) {
            for (int i = 7; i >= 0; i--) 
            {
                int bitData = (byteData >> i & 0x01);
                bit(bitData);
            }
        }
        void StartBit()
        {
            SDA(H); SCL(H);
            Thread.Sleep(1);
            SDA(L); SCL(H);
            Thread.Sleep(1);
        }
        void StopBit()
        {
            SDA(L); SCL(H);
            Thread.Sleep(1);
            SDA(H); SCL(H);
            Thread.Sleep(1);
        }
        void bit(int val) 
        {
            SCL(L);
            if (val == 0) SDA(L);
            else SDA(H);
            SCL(H);
            Thread.Sleep(1);
            SCL(L);
            SDA(H);
            Thread.Sleep(1);
        }

        void SCL(bool status)
        {
            serialPort1.DtrEnable = status;
        }
        void SDA(bool status)
        {
            serialPort1.RtsEnable = status;
        }

        int bacaBit() {
            int bitData = 0;
            SCL(L);
            SCL(H);
            bool bit = serialPort1.DsrHolding;
            if (bit == true) bitData = 1;
            Thread.Sleep(1);
            SCL(L);
            SDA(H);
            Thread.Sleep(1);
            return bitData;
        }

        public static byte[] StringToByteArray(string hex)
        {
            return Enumerable.Range(0, hex.Length)
                             .Where(x => x % 2 == 0)
                             .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
                             .ToArray();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            serialPort1.BaudRate = 9600;
            serialPort1.PortName = textBox1.Text;
            serialPort1.Open();


            //perintah Write
            StartBit();
            kirim(0xA0);
            bit(1); //ACK

            //Alamat memory (0x001)
            //0x00 
            kirim(0x00);
            bit(1); //ACK
            //0x01
            kirim(0x01);
            bit(1); //ACK

            //perintah Read
            kirim(0xA1);
            bit(1); //ACK


            int data = 0;
            for (int i = 7; i >= 0; i--)
            {
                data = data << 1;
                data = data | bacaBit();
            }
            bit(1); //ACK

            StopBit();


            serialPort1.Close();
            byte[] hasil = new byte[1]; hasil[0] = (byte)data;
            textBox2.Text = BitConverter.ToString(hasil);
        }
    }
}

Driver PL2303HX untuk Windows 10 64bit

Pernah beli alat USB to Serial Converter murah, dengan IC PL2303. Saat dipasang di komputer, ternyata butuh driver. Alhasil menemukan driver di situs produsen IC namun ada catatan :

Windows 8/8.1/10 are NOT supported in PL-2303HXA and PL-2303X EOL chip versions.

Untungnya ada situs yang baik hati (lupa dimana) memberikan file hasil modifikasi driver Windows 7 agar bisa dipasang di Windows 10.

Link: http://latiful.hayat.web.id/file/PL2303HX-edit.zip

Semoga bisa bermanfaat

Enkripsi: Rfc2898DeriveBytes di C# dan hash_pbkdf2 di php

C#

    public string DecryptText(string input, string password)
    {
        String[] tempAry = input.Split('-');

        byte[] bytesToBeDecrypted = new byte[tempAry.Length];
        for (int i = 0; i < tempAry.Length; i++)
            bytesToBeDecrypted[i] = Convert.ToByte(tempAry[i], 16);

        byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
        passwordBytes = SHA256.Create().ComputeHash(passwordBytes);

        byte[] bytesDecrypted = Decrypt(bytesToBeDecrypted, passwordBytes);

        return Encoding.UTF8.GetString(bytesDecrypted);

    }
    public byte[] Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
    {
        byte[] decryptedBytes = null;
        byte[] saltBytes = new byte[] { 5, 7, 3, 5, 2, 6, 7, 8 };
        using (MemoryStream ms = new MemoryStream())
        {
            using (RijndaelManaged AES = new RijndaelManaged())
            {
                AES.KeySize = 256;
                AES.BlockSize = 128;
                var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
                AES.Key = key.GetBytes(AES.KeySize / 8);
                AES.IV = key.GetBytes(AES.BlockSize / 8);
                AES.Mode = CipherMode.CBC;
                using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), 
                                                 CryptoStreamMode.Write))
                {
                    cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
                    cs.Close();
                }
                decryptedBytes = ms.ToArray();
            }
        }
        return decryptedBytes;
    }

PHP

function DecryptText ($input, $password){
    $tempAry = str_replace("-", "", $input);

    $bytesToBeDecryptedbin = hex2bin($tempAry); 
    $bytesToBeDecrypted = unpack('C*', $bytesToBeDecryptedbin);
    $bytesToBeDecryptedbinstring = "";
    for($i=0;$i<count($bytesToBeDecrypted);$i++){
        $bytesToBeDecryptedbinstring=$bytesToBeDecryptedbinstring.chr($bytesToBeDecrypted[$i+1]);
    }


    $passwordhash = hash('sha256', $password); 
    $passwordbin = hex2bin($passwordhash); 
    $passwordBytes = unpack('C*', $passwordbin);
    $passwordBytesstring = "";
    for($i=0;$i<count($passwordBytes);$i++){
        $passwordBytesstring=$passwordBytesstring.chr($passwordBytes[$i+1]);
    }

    $saltBytes = array(5,7,3,5,2,6,7,8);
    $saltBytesstring = "";
    for($i=0;$i<count($saltBytes);$i++){
        $saltBytesstring=$saltBytesstring.chr($saltBytes[$i]);
    }
    
    $keySize = 256; $blockSize = 128;

    $key = hash_pbkdf2("sha1", $passwordBytesstring, $saltBytesstring, 1000, 48, true); 
    $aeskey = (  substr($key,0,$keySize/8) );
    $aesiv =  (  substr($key,$keySize/8,$blockSize/8) );

    $decrypted = mcrypt_decrypt
          (
              MCRYPT_RIJNDAEL_128,
              $aeskey,
              $bytesToBeDecryptedbinstring,
              MCRYPT_MODE_CBC,
              $aesiv
           );        

    $result = "";
    for($i=0;$i<strlen($decrypted);$i++){
        if($decrypted[$i]==chr(7)) break;
        $result = $result . $decrypted[$i];
    }
           
    $decryptedarr = unpack('C*', $result);
    return $result;
}

sumber:

http://stackoverflow.com/questions/43011612/porting-c-sharp-rfc2898derivebytes-in-php-using-hash-pbkdf2

 

Compile x86 (32 bit) pada Visual studio x64 (64 bit)

Secara bawaan, Visual Studio akan meng-compile platform sama dengan jenis sistem operasinya. Jika menggunakan platform x64, maka hasil compilasinya juga x64. Bagaimana cara compile program x86 (32 bit) pada Visual studio yang dijalankan di Windows x64 (64 bit)

Buka: Tools > Options

pilih “Show all settings”

Arahkan ke “Projects and Solutions > General” dan tandai (centang) “Show advanced build configurations”

setelah klik OK, maka muncul pilihan x64 dan x86 pada drop-down.

Source: http://captain-slow.dk/2010/07/12/build-in-x86-on-a-x64-platform-with-microsoft-visual-c-2010-express/