Я пытаюсь создать двустороннюю связь между платой Arduino UNO и программой Python. Формат обмена сообщениями - JSON.
Поскольку Arduino UNO имеет входной буфер в 64 байта, а сообщения JSON значительно больше этого, я реализовал способ разбивать данные JSON на сообщения в 64 байта в Python, а затем собирать их в код Arduino.
Чтобы отметить конец сообщения, я использую строку "", информирующую и Arduino, и Python о том, что сообщение было полностью доставлено.
Код Arduino работает нормально при вводе данных через Arduino Serial Monitor. JSON, который я использую в качестве входных данных, приведен ниже. Две строки, отправляемые через последовательный монитор, по одной за раз.
{"sequence": 0, "state": 0, "commands": [{"device_id": "1", "val
ue": 1.0, "result": 0}], "statuses": [{"device_id": "1"}]}<e>
Выход для Serial Monitor следующий:
Но когда я запускаю тот же код Arduino с моим кодом Python, JSON, сгенерированный и отправленный обратно в Python, становится пустым ('{}').
Это мой код Arduino:
#include <ArduinoJson.h>
String inputMessage = "";
bool processingRequest = false;
void serialEventRun(void) {
if (Serial.available()) serialEvent();
}
void serialEvent() {
if (!processingRequest) {
String message = "";
char c;
while (Serial.available() > 0) {
c = Serial.read();
message.concat(c);
}
message.trim();
inputMessage += message;
if (inputMessage.endsWith("<e>")) {
processingRequest = true;
inputMessage = inputMessage.substring(0, inputMessage.indexOf("<e>"));
const size_t bufferSize = 2 * JSON_ARRAY_SIZE(3) + JSON_OBJECT_SIZE(2) + 6 * JSON_OBJECT_SIZE(3) + 240;
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonObject& root = jsonBuffer.parseObject(inputMessage);
const int sequence = root["sequence"];
const int state = root["state"];
JsonArray& commands = root["commands"];
JsonArray& statuses = root["statuses"];
// TODO include real command/status call
if (commands.size() > 0) {
for (int i = 0; i < commands.size(); i++) {
JsonObject& command = commands[i];
command["result"] = 1;
}
}
if (statuses.size() > 0) {
for (int i = 0; i < statuses.size(); i++) {
JsonObject& status = statuses[i];
status["value"] = 1.1;
status["health"] = 0;
}
}
root["state"] = 2;
root.printTo(Serial);
Serial.print("<e>");
processingRequest = false;
}
}
}
void setup() {
Serial.begin(115200);
}
void loop() {}
А это мой код Python:
import time
from serial import Serial
def main():
result = ''
serial_conn = Serial(port='COM5', baudrate=115200, timeout=0.1)
time.sleep(1)
serial_conn.write(str.encode('{"sequence": 0, "state": 0, "commands": [{"device_id": "1", "val'))
time.sleep(0.1)
serial_conn.write(str.encode('ue": 1.0, "result": 0}], "statuses": [{"device_id": "1"}]}<e>'))
time.sleep(0.1)
# serial_conn.flushInput()
while True:
# bytes_to_read = serial_conn.inWaiting()
# msg = serial_conn.read(bytes_to_read)
msg = serial_conn.readline()
time.sleep(0.1)
result += msg.decode()
print("<{}>".format(result))
if result.endswith('<e>'):
break
result = result.strip('<e>')
print("Message received: <{}>".format(result))
serial_conn.close()
if __name__ == '__main__':
main()
При работе с Python это вывод консоли:
<{}<e>>
Message received: <{}>
Process finished with exit code 0
Пытаясь выяснить, что происходит, я изменил код Arduino для вывода на последовательный порт только длины сериализованных данных JSON. При работе на Serial Monitor длина составляет 135, такая же длина выхода на скриншоте выше. Но при работе с Python длина равна 5, точно такой же длины "{} ", которую мы можем видеть в выводе консоли Python. Так что, очевидно, когда я работаю с Python, сериализация JSON генерирует пустые данные ("{}").
Я уже подумал, не следует ли печатать на последовательный порт (в коде Arduino), также с учетом 64-байтового буфера, как я делал при получении данных. Но поскольку сериализованные данные JSON генерируются пустыми, я не уверен, что это проблема.
Есть идеи?
Заранее спасибо!