using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; using ONNONLed5KSDKD; namespace BroadcastModule { public class BroadcastBoardManager { public List boardList; public Led5kSDK.bx_5k_area_header header_model; public BroadcastBoardManager() { header_model = new Led5kSDK.bx_5k_area_header(); header_model.AreaType = 0x06; //横向偏移 header_model.AreaX = 0; //纵向偏移 header_model.AreaY = 0; //宽度,需将点数除以8 header_model.AreaWidth = 32 / 8; //高度 header_model.AreaHeight = 32; //0自动循环显示 1完成后停留在最后一页 2超时未完成删除该信息 header_model.RunMode = 0; header_model.Reserved1 = 0; header_model.Reserved2 = 0; header_model.Reserved3 = 0; //1静止显示 2快速打出 3向左移动 4向右移动 5向上移动 6向下移动 header_model.DisplayMode = 0x02; header_model.ExitMode = 0x00; //1快-24慢 header_model.Speed = 5; //多少个0.5s header_model.StayTime = 6; //1单行 2多行 header_model.SingleLine = 0x01; //1手动换行 2自动 header_model.NewLine = 0x01; header_model.Timeout = 2; Led5kSDK.InitSdk(2, 2); boardList = new List(); //初始化时启动连接检查线程 Task.Factory.StartNew(() => { while (!Monitor.Monitor.isClosing) { Thread.Sleep(5000); foreach (BroadcastBoard bb in boardList) { try { bb.CheckConnection(5); } catch(Exception e) { Console.WriteLine("LED"+bb.boardParams.id+"连接:\n"+e.StackTrace); } } } }); } /// /// 增加屏幕 /// /// /// /// /// /// /// /// public bool AddScreen(int id, byte[] led_ip, uint led_port, Led5kSDK.bx_5k_card_type card_type, int tmout_sec, int mode) { uint hand = Led5kSDK.CreateClient(led_ip, led_port, card_type, tmout_sec, mode, null); BroadcastBoard bb = new BroadcastBoard(id, led_ip, led_port, card_type, hand); if (hand == 0) { boardList.Add(bb); return false; } else { bb.connected = true; bb.InitBoard(hand); boardList.Add(bb); return true; } } /// /// 关闭所有屏幕连接 /// public void DestroyAll() { foreach (BroadcastBoard bb in boardList) { //bb.RemoveDynamicAreas(bb.boardParams.handle); Led5kSDK.Destroy(bb.boardParams.handle); } } /// /// 删除特定屏幕连接 /// /// public void DestroyBoard(int index) { foreach (BroadcastBoard bb in boardList) { if (bb.boardParams.id == index) { bb.RemoveDynamicAreas(bb.boardParams.handle); Led5kSDK.Destroy(bb.boardParams.handle); } } } /// /// 时间同步 /// public bool UpdateTimeAll() { foreach (BroadcastBoard bb in boardList) { if (bb.boardParams.handle != 0) { int err = ONNONLed5KSDKD.Led5kSDK.CON_SytemClockCorrect(bb.boardParams.handle); if (err != 0) { return false; } } } return true; } } public class BroadcastBoard { public BoardParams boardParams; public bool connected; private Dictionary> handleDynamicAreasMap; private int volume = 10; public Led5kSDK.bx_5k_area_header header_model; public int ledScanState;// 0空闲 1正常 2前超界 3后超界 4左超界 5右超界 6测量失败 private int[] dispStatus; private bool isDisplaying; private object area1Lock; private object area2Lock; private string[] arrows = { "\\T001arrU64|\\n", "\\T001arrD64|\\n", "\\T001arrL64|\\n", "\\T001arrR64|\\n" }; //************************************************ 方法块 ************************************************** // *************** 公有方法 *************** public BroadcastBoard(int id, byte[] ip, uint port, Led5kSDK.bx_5k_card_type card_type, uint handle) { ledScanState = -1; isDisplaying = false; dispStatus = new int[2]; handleDynamicAreasMap = new Dictionary>(); header_model = new Led5kSDK.bx_5k_area_header(); area1Lock = new object(); area2Lock = new object(); boardParams = new BoardParams(id, ip, port, card_type, handle); } /// /// 检查连接状态 /// /// public bool CheckConnection(int sleptSec) { int count = 3; int result = -1; while (count > 0) { if (boardParams.handle != 0) { // 检查是否有内容在显示 int displaying = 0; lock (area1Lock) { displaying = dispStatus[0]; } lock (area2Lock) { displaying += dispStatus[1]; } if (displaying <= 0 && isDisplaying) { UpdateText("欢迎光临智象停车", 2, 0); UpdateArrow(-1, 2, 0); Console.WriteLine("LED清屏"); isDisplaying = false; } else { lock (area1Lock) { dispStatus[0] = dispStatus[0] >= 0 ? (dispStatus[0] - sleptSec) : 0; } lock (area2Lock) { dispStatus[1] = dispStatus[1] >= 0 ? (dispStatus[1] - sleptSec) : 0; } } result = Led5kSDK.CON_PING(boardParams.handle); Console.WriteLine("屏幕ping结果: " + result); if (result == 0) break; } else { boardParams.handle = Led5kSDK.CreateClient(boardParams.ip, boardParams.port, boardParams.card_type, 1, 2, null); } count--; if (count == 0 && result != 0 && boardParams.handle != 0) { Led5kSDK.Destroy(boardParams.handle); boardParams.handle = 0; } } connected = (result == 0 ? true : false); return connected; } /// /// 初始化控制板 /// /// /// public bool InitBoard(uint handle) { if (boardParams == null) return false; RemoveDynamicAreas(handle); //第一行128*16显示文字,上下8像素留空 AreaInfo area1 = new AreaInfo(handle, 0, Encoding.Default.GetBytes("")); area1.header.AreaWidth = 16;// 2=16/8 area1.header.AreaHeight = 16;//96 area1.header.AreaX = 0 / 8; // 8/8 area1.header.AreaY = 8; // 0 area1.header.SingleLine = 0x01; area1.header.NewLine = 0x02; area1.header.DisplayMode = 0x03; area1.header.StayTime = 10; area1.header.RunMode = 2; area1.header.Speed = 2; area1.header.Timeout = 20; //bb.header_model.AreaY = 16; area1.index = AddDynamicArea(handle, area1.header); if (area1.index != -1) { UpdateArea(handle, area1.index, Encoding.Default.GetBytes("")); boardParams.areas.Add(area1); } else { return false; } //第二、三行64*64显示一个指示标志 AreaInfo area2 = new AreaInfo(handle, 1, Encoding.Default.GetBytes("")); area2.header.AreaWidth = 8;// 8=64/8 area2.header.AreaHeight = 64; area2.header.AreaX = 32 / 8; // 8/8 area2.header.AreaY = 32; // 8/8 area2.header.SingleLine = 0x01; area2.header.NewLine = 0x01; area2.header.DisplayMode = 0x02; area2.header.StayTime = 20; area2.header.RunMode = 2; //area2.header.AreaX = (32 + 16) / 8; //area2.header.AreaY = 16; area2.index = AddDynamicArea(handle, area2.header); if (area2.index != -1) { UpdateArea(handle, area2.index, Encoding.Default.GetBytes("")); boardParams.areas.Add(area2); //bb.UpdateArea(handle, areaNoArrU, Encoding.Default.GetBytes("\\T000arrL|\\n\\T000arrU|\\n\\T000arrR|\\n\\T000arrD|")); } else { return false; } //顶角右偏32像素的8*8块专用于播放声音 AreaInfo areaSound = new AreaInfo(handle, 2, Encoding.Default.GetBytes("")); areaSound.header.AreaWidth = 2;// 2=16/8 areaSound.header.AreaHeight = 16; areaSound.header.SingleLine = 0x02; areaSound.header.NewLine = 0x02; areaSound.header.DisplayMode = 0x02; areaSound.header.StayTime = 1; areaSound.header.RunMode = 2; areaSound.header.AreaX = 0;// 32 / 8; areaSound.header.AreaY = 64; //0 areaSound.header.Speed = 4; areaSound.index = AddDynamicArea(handle, areaSound.header); if (areaSound.index != -1) { UpdateArea(handle, areaSound.index, Encoding.Default.GetBytes("")); boardParams.areas.Add(areaSound); //bb.UpdateArea(handle, areaNoArrU, Encoding.Default.GetBytes("\\T000arrL|\\n\\T000arrU|\\n\\T000arrR|\\n\\T000arrD|")); } else { return false; } return true; } /// /// 更新第一块区域文字信息 /// /// /// public bool UpdateText(string sentence, int waitSec, int runMode = -1,int dispMode = -1, bool horizontal = true, int slice = 6) { List sentenceContent = new List(); int i = 0; if (boardParams.handle == 0 || boardParams.areas.Count < 2) return false; // 竖屏 if (!horizontal) { while (i < sentence.Length) { if ((i + slice) % slice == 0) { if (i < sentence.Length - slice + 1) { char[] temp = (sentence.Substring(i, slice)).ToCharArray(); temp = temp.Reverse().ToArray(); sentenceContent.Add(new String(temp)); i = i + slice - 1; } else { sentenceContent.Add(new String(sentence.Substring(i).ToCharArray().Reverse().ToArray())); break; } } i++; } lock (area1Lock) { Task.Factory.StartNew(() => { int count = 0; UpdateArea(boardParams.handle, boardParams.areas[2].index, Encoding.Default.GetBytes(""), true, Encoding.Default.GetBytes(sentence), 10); while (count < sentenceContent.Count) { UpdateArea(boardParams.handle, boardParams.areas[0].index, Encoding.Default.GetBytes(sentenceContent[count])); Thread.Sleep(waitSec * 1000); count++; } }); } } // 横屏 else { Task.Factory.StartNew(() => { lock (area1Lock) { dispStatus[0] = waitSec; UpdateArea(boardParams.handle, boardParams.areas[2].index, Encoding.Default.GetBytes(""), true, Encoding.Default.GetBytes(sentence), 10, runMode, waitSec); UpdateArea(boardParams.handle, boardParams.areas[0].index, Encoding.Default.GetBytes(sentence + "\\n"), runMode, waitSec, dispMode); } if (sentence != "欢迎光临智象停车") { isDisplaying = true; } Console.WriteLine("index: " + boardParams.areas[0].index); Console.WriteLine("sentence: " + sentence); //if (runMode != 0) //{ // Thread.Sleep(waitSec*1000); // dispStatus[0] = false; //} }); } return true; } /// /// 更新下方箭头显示 /// /// /// public bool UpdateArrow(int index, int waitSec = 5, int runMode = -1) { if (index > 3) return false; if (boardParams.handle == 0 || boardParams.areas.Count < 2) return false; Task.Factory.StartNew(() => { lock (area2Lock) { dispStatus[1] = waitSec; if (index < 0) { UpdateArea(boardParams.handle, boardParams.areas[1].index, Encoding.Default.GetBytes(" "), runMode, waitSec); } else { UpdateArea(boardParams.handle, boardParams.areas[1].index, Encoding.Default.GetBytes(arrows[index]), runMode, waitSec); isDisplaying = true; } } //if (runMode != 0) //{ // Thread.Sleep(waitSec*1000); // dispStatus[1] = false; //} }); return true; } /// /// 删除某屏幕所有动态区 /// /// /// public bool RemoveDynamicAreas(uint handle) { if (!handleDynamicAreasMap.ContainsKey(handle)) { return false; } else { List list; handleDynamicAreasMap.TryGetValue(handle, out list); int err = 0; if (list != null) { for (int i = 0; i < list.Count; i++) { err += Led5kSDK.SCREEN_DelDynamicArea(handle, (byte)i); } } return err == 0 ? true : false; } } /// /// 删除某屏幕特定编号的动态区 /// /// /// /// public bool RemoveDynamicAreas(uint handle, int index) { if (!handleDynamicAreasMap.ContainsKey(handle)) { return false; } else { List list; handleDynamicAreasMap.TryGetValue(handle, out list); int err = 0; if (list != null) { for (int i = 0; i < list.Count; i++) { if (list[i].DynamicAreaLoc == index) { err = Led5kSDK.SCREEN_DelDynamicArea(handle, list[i].DynamicAreaLoc); return true; } } } return err == 0 ? true : false; } } // *************** 私有方法 *************** /// /// 增加动态区 /// /// /// private int AddDynamicArea(uint handle, Led5kSDK.bx_5k_area_header header) { List list; if (!handleDynamicAreasMap.ContainsKey(handle)) { list = new List(); list.Add(header); header.DynamicAreaLoc = 0; handleDynamicAreasMap.Add(handle, list); return 0; } else { handleDynamicAreasMap.TryGetValue(handle, out list); if (list != null) { int no = list[list.Count - 1].DynamicAreaLoc + 1; header.DynamicAreaLoc = (byte)(no); list.Add(header); return no; } return -1; } } /// /// 动态区域更新函数 /// /// private bool UpdateArea(uint handle, int index, byte[] areaText, int runMode = -1, int waitSec = -1, int dispMode = -1) { int err = -1; List list; if (!handleDynamicAreasMap.ContainsKey(handle)) { return false; } else { handleDynamicAreasMap.TryGetValue(handle, out list); if (list != null) { for (int i = 0; i < list.Count; i++) { if (index == list[i].DynamicAreaLoc) { Led5kSDK.bx_5k_area_header temp = list[i]; if (runMode >= 0 && runMode < 3) { temp.RunMode = (byte)runMode; } if(dispMode >= 0 && dispMode < 7) { temp.DisplayMode = (byte)dispMode; } if (waitSec >= 0) { temp.Timeout = (short)waitSec; } temp.DataLen = areaText.Length; handleDynamicAreasMap[handle][i] = temp; err = Led5kSDK.SCREEN_SendDynamicArea(handle, temp, (ushort)temp.DataLen, areaText); break; } } if (err == 0) return true; else return false; } else return false; } } /// /// 动态区域更新函数 /// /// private bool UpdateArea(uint handle, int index, byte[] areaText, bool soundOnly, byte[] soundText, int sound, int runMode = -1, int waitSec = -1, int dispMode = -1) { int err = -1; sound = sound > 10 ? 10 : sound; sound = sound < 1 ? 1 : sound; List list; if (!handleDynamicAreasMap.ContainsKey(handle)) { return false; } else { handleDynamicAreasMap.TryGetValue(handle, out list); if (list != null) { for (int i = 0; i < list.Count; i++) { if (index == list[i].DynamicAreaLoc) { Led5kSDK.bx_5k_area_header temp = list[i]; if (runMode >= 0 && runMode < 3) { temp.RunMode = (byte)runMode; } if (dispMode >= 0 && dispMode < 7) { temp.DisplayMode = (byte)dispMode; } if (waitSec >= 0) { temp.Timeout = (short)waitSec; } temp.DataLen = areaText.Length; handleDynamicAreasMap[handle][i] = temp; if (!soundOnly) err = Led5kSDK.SCREEN_SendSoundDynamicArea(handle, temp, (ushort)temp.DataLen, areaText, 2, 0, (byte)sound, 5, soundText.Length, soundText); else err = Led5kSDK.SCREEN_SendSoundDynamicArea(handle, temp, 0, Encoding.Default.GetBytes(""), 2, 0, (byte)sound, 5, soundText.Length, soundText); break; } } if (err == 0) return true; else return false; } else return false; } } ///// ///// 播放方法 ///// ///// 显示屏窗口ID ///// 播放模式 ///// 待显示或播语音字符串,输入“date”或“time”分别显示日期与时间 ///// 保持时间 ///// 存储块ID ///// 开始下标 ///// 结束下标 //public void Play(int winID, PlayMode mode, string str, int time = 0, int fieldID = 0, int startIndex = 0, int endIndex = 0) //{ // switch (mode) // { // case PlayMode.temporary: // DispString(winID, str, time); // break; // case PlayMode.download: // DownloadString(winID, str, fieldID); // break; // case PlayMode.readBuffer: // DispDownStr(winID, fieldID); // break; // case PlayMode.delete: // DelFile(winID, startIndex, endIndex); // break; // case PlayMode.audio: // AudioPlay(str); // break; // } //} } public class BoardParams { public int id; public byte[] ip; public uint port; public Led5kSDK.bx_5k_card_type card_type; public uint handle; public List areas; public BoardParams(int id, byte[] ip, uint port, Led5kSDK.bx_5k_card_type card_type, uint handle) { this.id = id; this.ip = ip; this.port = port; this.card_type = card_type; this.handle = handle; areas = new List(); } } public class AreaInfo { public uint winHandle; public int index; public bool display; public byte[] text; public Led5kSDK.bx_5k_area_header header; public AreaInfo(uint handle, int index, byte[] text) { this.winHandle = handle; this.index = index; this.text = text.ToArray(); header = new Led5kSDK.bx_5k_area_header(); } public override string ToString() { return winHandle + ", " + index + ", " + display + ", " + text.ToList().ToString(); } } }