/// <summary> /// Событие происходящее при получении данных /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) { // TODO: Мы получаем одну команду или набор? try { Command = ProtocolForEx.Unpack(((SerialPort)sender).BaseStream); // TODO: А куда деваем команды 1, 2 и другие, если они есть? //Если мы получаем более одной команды, то это уже противоречит //Логике работы нашего умного дома (одна команда - один ответ) if ((Command != null) && (Command.Count != 0)) { answer = (DevCommand)Command[0]; IsFindCommand = true; } } catch { } /*SerialPort sp = (SerialPort)sender; int counter = sp.ReadByte(); byte[] BytArray = new byte[counter]; BytArray[0] = (byte)counter; for (int i = 1; i < counter; i++) { BytArray[i] = (byte)sp.ReadByte(); } // Program.MyParser.ParssComand(BytArray); string Pank = sp.ReadExisting(); answer = BytArray;*/ }
/// <summary> /// Парсит ответ от контролера с учетом команды, присланной пользователем /// </summary> public void ParseAnswer(DevCommand Answer, string Com) { string[] SplitCom = Com.Split('/'); switch (SplitCom[0]) { case "SetParam": SetParamAnswer(Answer, SplitCom); break; case "AddDev": AddDevInDbAnswer(Answer); break; } }
public ArrayList Unpack(Stream dataStream) { byte buffer; byte count; bool IsFindComand = false; DevCommand comand; ArrayList result = new ArrayList(); int SubBuffer = (int)dataStream.ReadByte(); while (SubBuffer != -1) { try { buffer = (byte)SubBuffer; if ((buffer == 181) || (IsFindComand)) { comand = new DevCommand(); count = (byte)dataStream.ReadByte(); comand.len = count; comand.command = new byte[count - 5]; comand.port = (byte)dataStream.ReadByte(); comand.device = (byte)dataStream.ReadByte(); for (int i = 0; i < count - 5; i++) { comand.command[i] = (byte)dataStream.ReadByte(); } if (dataStream.ReadByte() != 74) { } else { result.Add(comand); } IsFindComand = false; } else { while ((SubBuffer != 181) || (SubBuffer != -1)) { SubBuffer = (byte)dataStream.ReadByte(); } } SubBuffer = (int)dataStream.ReadByte(); } catch { return result; } } return result; }
/// <summary> /// Метод отправки данных /// </summary> /// <param name="ByteArray">Данные для отправки</param> public DevCommand SendInform(byte[] ByteArray) { OpenCom(); answer = new DevCommand(); IsFindCommand = false; numbOfWrite = 0; MyComExecutable.Write(ByteArray, 0, ByteArray.Length); DevCommand comand = WaitAnswer(); Close(); return comand; }
/// <summary> /// Посылает команды на ком порт исполнитель с учетом всех блокировок /// </summary> /// <param name="Inform"></param> /// <returns></returns> private DevCommand SendInformInCom(byte[] Inform) { DevCommand Answer = new DevCommand(); // Флаг который означает что КомПорт блокирован bool podflag = false; //Процедура отправки команды через ком порт исполнитель с соблюдением //синхронизации потоков while (!podflag) { lock (Storage.lockerComPort) { if (Storage.flagComPort) { podflag = true; Storage.flagComPort = false; Answer = ExeComPort.SendInform(Inform); Storage.flagComPort = true; } } //Чтобы оптимизировать работу службы ожидаем освобождения ком порта исполнителя //поток засыпает if (!podflag) { Thread.Sleep(6000); } } return Answer; }
/// <summary> /// Обработка команд от TCP сервера /// </summary> /// <param name="comand">Команда пользователя</param> public void ProcessThreadTCP(object comand) { string MainComand = comand.ToString(); string[] SplitByUser = MainComand.Split('@'); byte[] ComandForComPort = DM.Parser(SplitByUser[0], SplitByUser[1]); DevCommand Answer = new DevCommand(); if (ComandForComPort[0] != 0) { Answer = SendInformInCom(ComandForComPort); DM.ParseAnswer(Answer, SplitByUser[0]); } // Удалем поток из пула потоков _threads.Remove(Thread.CurrentThread); }
/// <summary> /// Обработка команд от порта слушателя /// </summary> /// <param name="comand">Команда от порта слушателя</param> public void ProcessThreadList(object comand) { //Получаем команду для порта исполнителя byte[] ProcComand = ExDM.ParserComand(comand); DevCommand Answer = new DevCommand(); if (ProcComand[0] != 0) { Answer = SendInformInCom(ProcComand); ExDM.ParserAnswer(Answer); } // Удалем поток из пула потоков _threads.Remove(Thread.CurrentThread); }
/// <summary> /// Парсит ответ от контролера установил, контролер значение или нет /// </summary> private void SetParamAnswer(DevCommand Answer, string[] SplitCom) { try { if (Answer.command[0] == 1) { BdDevice.UpdateDeviceState(Answer.port, Answer.device, Convert.ToInt32(SplitCom[2])); } else { string Mess = "Устройство " + SplitCom[1] + " не изменило свое состояние!"; WinLog.Write(Mess, System.Diagnostics.EventLogEntryType.Error); } } catch { string Mess = "Устройство " + SplitCom[1] + " не изменило свое состояние!"; WinLog.Write(Mess, System.Diagnostics.EventLogEntryType.Error); } }
/// <summary> /// Метод, который формирует команду для изменения состояния /// устроив Формат команды который был SetParam/ИмяУстройства/Параметр /// </summary> /// <param name="SplitComand">Массив которы содержит команду от пользователя</param> /// <returns></returns> private byte[] SetParam(string[] SplitComand) { DevCommand ForNum = new DevCommand(); byte[] MyDC; if (SplitComand[1] != "") { ForNum = BdDevice.DeterDevByName(SplitComand[1]); int Com = Convert.ToInt32(SplitComand[2]); //Перевод int переменной в массив из байт byte[] intBytes = BitConverter.GetBytes(Com); if (BitConverter.IsLittleEndian) Array.Reverse(intBytes); MyDC = ProtocolForDM.Pack(ForNum.port,ForNum.device, intBytes); } else { MyDC = new byte[1]; MyDC[0] = 0; } return MyDC; }
/// <summary> /// Метод обрабатывает отвте от контролера, в котором содержится состояние нового добавленного устройства. /// </summary> private void AddDevInDbAnswer(DevCommand Answer) { try { if (BitConverter.IsLittleEndian) Array.Reverse(Answer.command); int i = BitConverter.ToInt32(Answer.command, 0); BdDevice.UpdateDeviceState(Answer.port, Answer.device, i); } catch { WinLog.Write("Не удалось обновить состояние устройства, после его добавления", System.Diagnostics.EventLogEntryType.Error); } }
/// <summary> /// Метод возвращает номер порта и номер устройства по имени /// </summary> /// <param name="Name">Имя устройства</param> /// <returns></returns> public DevCommand DeterDevByName(string Name) { DevCommand Result = new DevCommand(); lock (Storage.lockerBdDev) { // Ожадаем пока не закончится начатая транзакция while (SQL.IsLockedTransaction) Thread.Sleep(5); // Устанавливаем признак начала транзакции SQL.IsLockedTransaction = true; // Выполняем транзакцию if (SQL.FB_dbConnection != null) try { if (SQL.FB_dbConnection.State == ConnectionState.Closed) SQL.FB_dbConnection.Open(); using (FbTransaction transaction = SQL.FB_dbConnection.BeginTransaction(SQL.FB_dbReadTransactionOptions)) { string Query = "select NumOfPort, NumOfDev" + " from Device " + " where Name = '" + Name + "' Rows(1)"; using (FbCommand command = new FbCommand(Query, SQL.FB_dbConnection, transaction)) using (FbDataReader r = command.ExecuteReader()) { if (r.Read()) { if (r.IsDBNull(0)) { Result.len = 0; } else { if (!r.IsDBNull(1)) { Result.port = (byte)r.GetInt32(0); Result.device = (byte)r.GetInt16(1); Result.len = 3; } else { Result.len = 0; } } } } transaction.Commit(); } } catch { Result.len = 0; WinLog.Write("Не удалось определить порт устройства по его имени", System.Diagnostics.EventLogEntryType.Error); SQL.IsLockedTransaction = false; return Result; } // Сбрасываем признак транзакции SQL.IsLockedTransaction = false; } return Result; }