Initial commit
This commit is contained in:
455
Handler/Project/Device/KeyenceBarcode.cs
Normal file
455
Handler/Project/Device/KeyenceBarcode.cs
Normal file
@@ -0,0 +1,455 @@
|
||||
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;
|
||||
|
||||
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($"키엔스비트맵호환오류 원본:{source.Width}x{source.Height} => 대상:{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 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("키엔스 이미지를 받고 잇어 명령을 처리하지 않음");
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user