480 lines
14 KiB
C#
480 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Drawing.Imaging;
|
|
using System.Runtime.InteropServices;
|
|
using AR;
|
|
using System.Security.Cryptography;
|
|
|
|
namespace Project.Device
|
|
{
|
|
public class KeyenceBarcode : IDisposable
|
|
{
|
|
public string IP { get; set; }
|
|
public int Port { get; set; }
|
|
private Winsock_Orcas.Winsock ws;
|
|
public event EventHandler<RecvDataEvent> BarcodeRecv;
|
|
public event EventHandler<RecvImageEvent> ImageRecv;
|
|
RecvDataEvent LastData = null;
|
|
RecvImageEvent LastImage = null;
|
|
|
|
public Boolean IsTriggerOn { get; set; } = false;
|
|
private DateTime LastTrigOnTime = DateTime.Now;
|
|
private System.Threading.Thread thliveimage = null;
|
|
public int LiveImagetDelay = 500;
|
|
public bool disposed = false;
|
|
bool bRunConnectionK = true;
|
|
public string Tag { get; set; }
|
|
|
|
|
|
public string baseZPL { get; set; }
|
|
|
|
public class RecvDataEvent : EventArgs
|
|
{
|
|
public string RawData { get; set; }
|
|
public RecvDataEvent(string rawdata)
|
|
{
|
|
this.RawData = rawdata;
|
|
}
|
|
}
|
|
public class RecvImageEvent : EventArgs
|
|
{
|
|
public Image Image { get; set; }
|
|
public RecvImageEvent(Image rawdata)
|
|
{
|
|
this.Image = rawdata;
|
|
}
|
|
}
|
|
|
|
public KeyenceBarcode(string ip = "192.168.100.100", int port = 9004)
|
|
{
|
|
this.IP = ip;
|
|
this.Port = port;
|
|
ws = new Winsock_Orcas.Winsock();
|
|
ws.LegacySupport = true;
|
|
ws.DataArrival += Ws_DataArrival;
|
|
ws.Connected += Ws_Connected;
|
|
thliveimage = new Thread(new ThreadStart(GetLiveImage));
|
|
thliveimage.IsBackground = false;
|
|
thliveimage.Start();
|
|
Console.WriteLine($"{ip} / Port:{port}");
|
|
}
|
|
|
|
~KeyenceBarcode()
|
|
{
|
|
Dispose(disposing: false);
|
|
}
|
|
public void Dispose()
|
|
{
|
|
Dispose(disposing: true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
#region "Image Utility"
|
|
|
|
/// <summary>
|
|
/// 8bpp 이미지의 팔레트를 설정합니다
|
|
/// </summary>
|
|
/// <param name="bmp"></param>
|
|
public void UpdateGrayPallete(ref Bitmap bmp)
|
|
{
|
|
if (bmp.PixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
|
|
{
|
|
System.Drawing.Imaging.ColorPalette pal = bmp.Palette;
|
|
for (int i = 0; i < 256; i++)
|
|
{
|
|
pal.Entries[i] = Color.FromArgb(i, i, i);
|
|
}
|
|
bmp.Palette = pal;
|
|
}
|
|
}
|
|
public void GetImagePtr(Bitmap bmp, out IntPtr ptr, out int stride)
|
|
{
|
|
stride = 0;
|
|
ptr = IntPtr.Zero;
|
|
try
|
|
{
|
|
BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
|
|
ptr = bmpdata.Scan0;
|
|
stride = bmpdata.Stride;
|
|
bmp.UnlockBits(bmpdata);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
public bool IsCompatible(Bitmap source, Bitmap target)
|
|
{
|
|
if (source == null) return false;
|
|
try
|
|
{
|
|
if (source.Height != target.Height ||
|
|
source.Width != target.Width ||
|
|
source.PixelFormat != target.PixelFormat) return false;
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
PUB.log.AddE("keyence compatiable : " + ex.Message);
|
|
return false;
|
|
}
|
|
|
|
|
|
}
|
|
public bool IsCompatible(Bitmap source, int w, int h, PixelFormat pf)
|
|
{
|
|
if (source == null) return false;
|
|
if (source.Height != h ||
|
|
source.Width != w ||
|
|
source.PixelFormat != pf) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
public Bitmap CreateBitmap(int w, int h)
|
|
{
|
|
|
|
Bitmap bmp = new Bitmap(w, h, PixelFormat.Format8bppIndexed);
|
|
UpdateGrayPallete(ref bmp);
|
|
return bmp;
|
|
}
|
|
|
|
byte[] memorybuffer;
|
|
public void UpdateBitmap(Bitmap source, Bitmap target)
|
|
{
|
|
if (source.Width < 10 || source.Height < 10) return;
|
|
if (target == null || target.Width < 10 || target.Height < 10)
|
|
{
|
|
target = CreateBitmap(source.Width, source.Height);
|
|
}
|
|
|
|
var bitmaperrcnt = AR.VAR.I32[eVarInt32.BitmapCompatErr];
|
|
if (IsCompatible(source, target) == false)
|
|
{
|
|
PUB.log.AddE($"Keyence bitmap compatibility error Source:{source.Width}x{source.Height} => Target:{target.Width}x{target.Height}");
|
|
|
|
if (bitmaperrcnt > 5)
|
|
{
|
|
var o = target;
|
|
target = CreateBitmap(source.Width, source.Height);
|
|
if (o != null) o.Dispose();
|
|
bitmaperrcnt = 0;
|
|
}
|
|
else AR.VAR.I32[eVarInt32.BitmapCompatErr] += 1;
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (bitmaperrcnt > 0)
|
|
AR.VAR.I32[eVarInt32.BitmapCompatErr] = 0;
|
|
}
|
|
|
|
//get image pointer
|
|
BitmapData bmpdatas = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, source.PixelFormat);
|
|
var ptrs = bmpdatas.Scan0;
|
|
var strides = bmpdatas.Stride;
|
|
|
|
BitmapData bmpdatat = target.LockBits(new Rectangle(0, 0, target.Width, target.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, target.PixelFormat);
|
|
var ptrt = bmpdatat.Scan0;
|
|
var stridet = bmpdatat.Stride;
|
|
|
|
//read source data
|
|
var sourcesize = Math.Abs(bmpdatas.Stride) * source.Height;
|
|
if (memorybuffer == null || memorybuffer.Length != sourcesize)
|
|
{
|
|
memorybuffer = new byte[sourcesize];
|
|
}
|
|
|
|
Marshal.Copy(ptrs, memorybuffer, 0, sourcesize);
|
|
|
|
//write target data
|
|
Marshal.Copy(memorybuffer, 0, ptrt, sourcesize);
|
|
|
|
source.UnlockBits(bmpdatas);
|
|
target.UnlockBits(bmpdatat);
|
|
|
|
}
|
|
|
|
public void UpdateBitmap(Bitmap target, byte[] buffer, int w, int h)
|
|
{
|
|
if (IsCompatible(target, w, h, target.PixelFormat) == false)
|
|
{
|
|
throw new Exception("cannot udate incompatible bitmap.");
|
|
}
|
|
|
|
//get image pointer
|
|
BitmapData bmpdata = target.LockBits(new Rectangle(0, 0, target.Width, target.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, target.PixelFormat);
|
|
var ptr = bmpdata.Scan0;
|
|
var stride = bmpdata.Stride;
|
|
|
|
|
|
if (stride == w) //image x4
|
|
{
|
|
Marshal.Copy(buffer, 0, ptr, stride * h);
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < target.Height; ++i)
|
|
{
|
|
Marshal.Copy(buffer, i * w, new IntPtr(ptr.ToInt64() + i * stride), w);
|
|
}
|
|
}
|
|
|
|
target.UnlockBits(bmpdata);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (!this.disposed)
|
|
{
|
|
if (disposing)
|
|
{
|
|
//dipose managed resources;
|
|
bRunConnectionK = false;
|
|
Trigger(false);
|
|
ws.DataArrival -= Ws_DataArrival;
|
|
ws.Connected -= Ws_Connected;
|
|
Disconnect();
|
|
if (thliveimage != null && thliveimage.IsAlive) thliveimage.Abort();
|
|
}
|
|
|
|
//dispose unmmanged resources;
|
|
}
|
|
|
|
disposed = true;
|
|
}
|
|
|
|
void GetLiveImage()
|
|
{
|
|
while (bRunConnectionK)
|
|
{
|
|
if (IsConnect && IsTriggerOn)
|
|
{
|
|
var tagname = this.Tag;
|
|
var img = GetImage();
|
|
this.LastImage = new RecvImageEvent(img);
|
|
ImageRecv?.Invoke(this, this.LastImage);
|
|
System.Threading.Thread.Sleep(LiveImagetDelay);
|
|
}
|
|
else System.Threading.Thread.Sleep(1000);
|
|
}
|
|
}
|
|
|
|
private void Ws_Connected(object sender, Winsock_Orcas.WinsockConnectedEventArgs e)
|
|
{
|
|
this.Trigger(true);
|
|
}
|
|
|
|
public void Connect()
|
|
{
|
|
if (this.ws.State == Winsock_Orcas.WinsockStates.Closed)
|
|
{
|
|
this.ws.RemoteHost = this.IP;
|
|
this.ws.RemotePort = this.Port;
|
|
this.ws.Connect();
|
|
}
|
|
|
|
}
|
|
public void Disconnect()
|
|
{
|
|
if (this.ws.State != Winsock_Orcas.WinsockStates.Closed)
|
|
this.ws.Close();
|
|
}
|
|
|
|
private void Ws_DataArrival(object sender, Winsock_Orcas.WinsockDataArrivalEventArgs e)
|
|
{
|
|
var data = ws.Get<string>();
|
|
this.LastData = new RecvDataEvent(data);
|
|
BarcodeRecv?.Invoke(this, LastData);
|
|
}
|
|
|
|
public bool Reset()
|
|
{
|
|
//if (IsTriggerOn) return;
|
|
string cmd = "RESET";
|
|
if (IsConnect == false)
|
|
{
|
|
PUB.log.AddE("Keyence Not Connected : RESET");
|
|
return false;
|
|
}
|
|
try
|
|
{
|
|
ws.Send(cmd + "\r");
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
PUB.log.AddE(ex.Message);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public bool BSave(int no)
|
|
{
|
|
var cmd = $"BSAVE,{no}";
|
|
try
|
|
{
|
|
ws.Send(cmd + "\r");
|
|
return true;
|
|
}
|
|
catch {
|
|
return false;
|
|
}
|
|
}
|
|
public bool BLoad(int no)
|
|
{
|
|
var cmd = $"BLOAD,{no}";
|
|
try
|
|
{
|
|
ws.Send(cmd + "\r");
|
|
return true;
|
|
}
|
|
catch {
|
|
return false;
|
|
}
|
|
}
|
|
public void Trigger(bool bOn)
|
|
{
|
|
//if (IsTriggerOn) return;
|
|
string cmd = bOn ? "LON" : "LOFF";
|
|
|
|
if (bOn) LastTrigOnTime = DateTime.Now;
|
|
|
|
try
|
|
{
|
|
ws.Send(cmd + "\r");
|
|
IsTriggerOn = bOn;
|
|
}
|
|
catch { }
|
|
}
|
|
public void ExecCommand(string cmd)
|
|
{
|
|
try
|
|
{
|
|
ws.Send(cmd + "\r");
|
|
}
|
|
catch { }
|
|
}
|
|
public bool IsConnect
|
|
{
|
|
get
|
|
{
|
|
if (ws == null) return false;
|
|
return ws.State == Winsock_Orcas.WinsockStates.Connected;
|
|
}
|
|
}
|
|
|
|
private bool readimage = false;
|
|
ManualResetEvent mre = new ManualResetEvent(true);
|
|
bool mreSetOK = true;
|
|
bool mreResetOK = true;
|
|
|
|
public Image GetImage()
|
|
{
|
|
Image oimg = null;
|
|
if (mreResetOK && mre.WaitOne(1000) == false)
|
|
{
|
|
mreResetOK = false;
|
|
return oimg;
|
|
}
|
|
else
|
|
{
|
|
mreResetOK = mre.Reset();
|
|
try
|
|
{
|
|
var url = $"http://{this.IP}/liveimage.jpg";
|
|
var data = UTIL.DownloadImagefromUrl(url);
|
|
var ms = new System.IO.MemoryStream(data);
|
|
oimg = Image.FromStream(ms);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
PUB.log.AddE("Keyence GetImage:" + ex.Message);
|
|
}
|
|
|
|
if (mreResetOK)
|
|
{
|
|
mreSetOK = mre.Set();
|
|
}
|
|
}
|
|
return oimg;
|
|
}
|
|
|
|
public bool SaveImage(string fn)
|
|
{
|
|
var fi = new System.IO.FileInfo(fn);
|
|
if (fi.Directory.Exists == false)
|
|
fi.Directory.Create();
|
|
|
|
|
|
|
|
if (mreResetOK && mre.WaitOne(1000) == false)
|
|
{
|
|
mreResetOK = false;
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
bool retval = false;
|
|
mreResetOK = mre.Reset();
|
|
try
|
|
{
|
|
var url = $"http://{this.IP}/liveimage.jpg";
|
|
var data = UTIL.DownloadImagefromUrl(url);
|
|
using (var ms = new System.IO.MemoryStream(data))
|
|
{
|
|
using (var oimg = Image.FromStream(ms))
|
|
oimg.Save(fi.FullName);
|
|
}
|
|
retval = true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
|
|
}
|
|
if (mreResetOK)
|
|
mre.Set();
|
|
return retval;
|
|
}
|
|
}
|
|
|
|
public bool UpdateKeyenceImage(ref System.Windows.Forms.PictureBox pic)
|
|
{
|
|
bool retval = false;
|
|
if (readimage)
|
|
{
|
|
PUB.log.AddAT("Keyence is receiving image, command not processed");
|
|
}
|
|
else
|
|
{
|
|
readimage = true;
|
|
var oimg = pic.Image;
|
|
|
|
var newimage = GetImage();
|
|
|
|
pic.Image = newimage;
|
|
retval = newimage != null;
|
|
if (oimg != null) oimg.Dispose();
|
|
|
|
}
|
|
readimage = false;
|
|
return retval;
|
|
}
|
|
}
|
|
}
|