internal void ParseDataMessage(ArraySegment <byte> dataMessage, MessageType message, object[] parameters, bool fromPrinter) { ReadOnlySpan <byte> buffer = dataMessage.AsSpan(); int dataIndex = 0; MessageDescription messageDescription = MessageDescription.Find(message); string messageFormat = fromPrinter ? messageDescription.PrinterFormat : messageDescription.ProgramFormat; int parameterIndex = 0; for (int formatIndex = 0; formatIndex < messageFormat.Length; formatIndex++) { char c = messageFormat[formatIndex]; if (c == 'T' || c == 'B' || c == 'W' || c == 'Z' || c == 'Y' || c == 'Q' || c == 'q') { ReadOnlySpan <byte> parameterData; // If it is last token, take everything until the end. if (formatIndex + 1 == messageFormat.Length) { parameterData = buffer.Slice(dataIndex); } else { char nc = messageFormat[formatIndex + 1]; // If next token is text or number, we know use known size if (nc == 'T' || nc == 'B' || nc == 'W' || nc == 'Z' || nc == 'Y') { if (c == 'W') { parameterData = buffer.Slice(dataIndex, 4); } else if (c == 'Y') { parameterData = buffer.Slice(dataIndex, 7); } else if (c == 'Z') { parameterData = buffer.Slice(dataIndex, 4); } else { parameterData = buffer.Slice(dataIndex, 1); } } else { byte endByte = (byte)nc; parameterData = buffer.Slice(dataIndex); for (int i = 0; i < parameterData.Length; i++) { if (parameterData[i] == endByte) { parameterData = parameterData.Slice(0, i); break; } } } } dataIndex += parameterData.Length; switch (c) { case 'W': { int number = 0; for (int i = 0; i < 4; i++) { number = number * 16 + ((parameterData[i] >= 'A') ? (parameterData[i] - 'A' + 10) : (parameterData[i] - '0')); } Store(number, parameters[parameterIndex++]); } break; case 'T': case 'B': byte[] stringBytes = new byte[parameterData.Length]; int stringBytesUsed = 0; for (int i = 0; i < parameterData.Length; i++) { if (parameterData[i] == 16) { stringBytes[stringBytesUsed++] = (byte)(parameterData[++i] + 64); } else { stringBytes[stringBytesUsed++] = parameterData[i]; } } var s = ToString(stringBytes, stringBytesUsed); if (c == 'T') { Store(s, parameters[parameterIndex++]); } else { Store(double.Parse(s), parameters[parameterIndex++]); } break; case 'Q': // TODO: Implement this break; case 'q': // TODO: Implement this break; // TODO: Remove this as it looks like it is not used!!! case 'Y': { int day, month, year; day = parameterData[0] - '0' * 10 + parameterData[1] - '0'; month = parameterData[3] - '0' * 10 + parameterData[4] - '0'; year = parameterData[5] - '0' * 10 + parameterData[6] - '0'; Store(day, parameters[parameterIndex++]); Store(month, parameters[parameterIndex++]); Store(year, parameters[parameterIndex++]); } break; case 'Z': { int hours, minutes; hours = parameterData[0] - '0' * 10 + parameterData[1] - '0'; minutes = parameterData[2] - '0' * 10 + parameterData[3] - '0'; Store(hours, parameters[parameterIndex++]); Store(minutes, parameters[parameterIndex++]); } break; } } else { byte expectedByte = (byte)c; if (buffer[dataIndex] != expectedByte) { throw new IllFormedMessageException($"Encountered byte {buffer[dataIndex]} [{(char)buffer[dataIndex]}] while expecting {expectedByte} [{(char)expectedByte}]"); } dataIndex++; } } }
internal ArraySegment <byte> CreateDataMessage(byte[] messageBuffer, MessageType message, object[] parameters, bool fromPrinter) { int length = 0; MessageDescription messageDescription = MessageDescription.Find(message); string messageFormat = fromPrinter ? messageDescription.PrinterFormat : messageDescription.ProgramFormat; int parameterIndex = 0; foreach (char c in messageFormat) { switch (c) { case 'W': int a = Convert.ToInt32(parameters[parameterIndex++]); for (int i = 0; i < 4; i++, a /= 16) { messageBuffer[length + 3 - i] = (byte)((a % 16 >= 10) ? (a % 16 - 10 + 'A') : (a % 16 + '0')); } length += 4; break; case 'B': string number = parameters[parameterIndex++]?.ToString() ?? string.Empty; foreach (var cc in ToBytes(number)) { messageBuffer[length++] = cc; } break; case 'T': string text = parameters[parameterIndex++]?.ToString() ?? string.Empty; foreach (var cc in ToBytes(text)) { if (cc >= 0 && cc < 32) { messageBuffer[length++] = 16; messageBuffer[length++] = (byte)(cc + 64); } else { messageBuffer[length++] = cc; } } break; case 'Q': { DateTime dt = (DateTime)parameters[parameterIndex++]; messageBuffer[length++] = (byte)(dt.Day / 10 + '0'); messageBuffer[length++] = (byte)(dt.Day % 10 + '0'); messageBuffer[length++] = (byte)'-'; messageBuffer[length++] = (byte)(dt.Month / 10 + '0'); messageBuffer[length++] = (byte)(dt.Month % 10 + '0'); messageBuffer[length++] = (byte)'-'; messageBuffer[length++] = (byte)(dt.Year % 100 / 10 + '0'); messageBuffer[length++] = (byte)(dt.Year % 10 + '0'); messageBuffer[length++] = (byte)' '; messageBuffer[length++] = (byte)(dt.Hour / 10 + '0'); messageBuffer[length++] = (byte)(dt.Hour % 10 + '0'); messageBuffer[length++] = (byte)'-'; messageBuffer[length++] = (byte)(dt.Minute / 10 + '0'); messageBuffer[length++] = (byte)(dt.Minute % 10 + '0'); } break; case 'q': { DateTime dt = (DateTime)parameters[parameterIndex++]; messageBuffer[length++] = (byte)(dt.Day / 10 + '0'); messageBuffer[length++] = (byte)(dt.Day % 10 + '0'); messageBuffer[length++] = (byte)'-'; messageBuffer[length++] = (byte)(dt.Month / 10 + '0'); messageBuffer[length++] = (byte)(dt.Month % 10 + '0'); messageBuffer[length++] = (byte)'-'; messageBuffer[length++] = (byte)(dt.Year % 100 / 10 + '0'); messageBuffer[length++] = (byte)(dt.Year % 10 + '0'); messageBuffer[length++] = (byte)' '; messageBuffer[length++] = (byte)(dt.Hour / 10 + '0'); messageBuffer[length++] = (byte)(dt.Hour % 10 + '0'); messageBuffer[length++] = (byte)'-'; messageBuffer[length++] = (byte)(dt.Minute / 10 + '0'); messageBuffer[length++] = (byte)(dt.Minute % 10 + '0'); messageBuffer[length++] = (byte)'-'; messageBuffer[length++] = (byte)(dt.Second / 10 + '0'); messageBuffer[length++] = (byte)(dt.Second % 10 + '0'); } break; default: messageBuffer[length++] = (byte)c; break; // TODO: Remove this as it looks like it is not used!!! case 'Y': // TODO: Use DateTime structure instead of three arguments int day = Convert.ToInt32(parameters[parameterIndex++]); int month = Convert.ToInt32(parameters[parameterIndex++]); int year = Convert.ToInt32(parameters[parameterIndex++]); messageBuffer[length++] = (byte)(day / 10 + '0'); messageBuffer[length++] = (byte)(day % 10 + '0'); messageBuffer[length++] = (byte)'0'; messageBuffer[length++] = (byte)(month / 10 + '0'); messageBuffer[length++] = (byte)(month % 10 + '0'); messageBuffer[length++] = (byte)(year / 10 + '0'); messageBuffer[length++] = (byte)(year % 10 + '0'); break; case 'Z': // TODO: Use DateTime structure instead of two arguments int hour = Convert.ToInt32(parameters[parameterIndex++]); int minute = Convert.ToInt32(parameters[parameterIndex++]); messageBuffer[length++] = (byte)(hour / 10 + '0'); messageBuffer[length++] = (byte)(hour % 10 + '0'); messageBuffer[length++] = (byte)(minute / 10 + '0'); messageBuffer[length++] = (byte)(minute % 10 + '0'); break; } } return(new ArraySegment <byte>(messageBuffer, 0, length)); }