Определение формата пакета данных разных сенсоров для передачи по радио
- Войдите на сайт для отправки комментариев
всем привет.
есть несколько девайсов на базе arduino + RFM95(LoRa) - серверов - которые по запросу снимают данные со своих сенсоров и передают эти данные на _одно_ клиентское устройство.
сейчас это сделано так - для сбора данных и передачи их на сервере используется array of float:
float data_buf[23]; //[0]-[14]: ext thermosensors, //[15]: int sensor, //[16]: batV, //[17]: RSSI, //[18]: Vcc, //[19]: light, //[20]: snow_depth, //[21]: LRF temp, //[22]: LRF Vcc
и на стороне клиента я использую такой же массив для получения и дальнейшего вывода данных.
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN]; uint8_t len = sizeof(buf); uint8_t from; if (manager.recvfromAckTimeout(buf, &len, 5000, &from)) { Serial.print(F("T0:"));Serial.println((*(float *)&buf[0])); // buf[0] Serial.print(F("T1:"));Serial.println((*(float *)&buf[4])); // buf[1] .............................. etc
но некоторые серверы имеют разное кол-вол термосенсоров и, например, есть или нет лазерный сенсор и так далее..
поэтому я хочу сделать так, чтобы в коде каждого сервера были определены существующие у него сенсоры, а на клиенте сделать универсальный код, который получает и выводит данные с разный серверов.
например:
сервер1 - 5 термосенсоров:
typedef struct { float temp1; float temp2; float temp3; float temp4; float temp5; float light; float vcc; } Payload; Payload srv_data;
сервер2 - 10 термосенсоров:
typedef struct { float temp1; float temp2; float temp3; float temp4; float temp5; ............................. float temp10; float light; float vcc; float snow_depth; } Payload; Payload srv_data;
но вот какой должен быть код на клиенте, чтобы он одинаково обрабатывал полученные данные от 1 и 2 сервера, и выводил их корректно?
прошу совета, и если можно - пример кода.
или хотябы что читать на эту тему.
может быть тут struct и не нужен. например, по идее можно на сервере формировать пакет данный в текстовом виде и клиент при получении будет просто выводить то, что приехало в тексте..
но массив или другой структурированый пакет данных вроде бы красивее выглядит.
спасибо заранее
простите, но какая-то хрень написана. Сначала описан массив флоат(почему флоат?), но потом принимается массив байт.
Вы разницу между флоатом и байтом понимаете? Который из двух вам реально нужен?
сервер1 - 5 термосенсоров:
сервер2 - 10 термосенсоров:
В начало каждой структуры добавьте её длину. А при чтении, сначала читайте длину, потом запрашивайте нужный буфер и читайте остальное. так сделано в Windows API со многими структурами.
В начало каждой структуры добавьте её длину. А при чтении, сначала читайте длину, потом запрашивайте нужный буфер и читайте остальное. так сделано в Windows API со многими структурами.
спасибо за идею.. значит мне нужно добавить в структуру еще одно служебное поле - length, в котором итоговое указываю кол-во байт, которое занимают все данные, что собираются на этом конкретном сервере.
эх.. примерчик бы не помешал) особенно как это потом читать на клиенте учитывая полученный length.
но вот что еще - как быть если в каком то сервере будет всего 10 термосенсоров == 40 байт
а в другом сервере будет тоже 40 байт, но данные будут распределены, например 5 термо и 5 датчиков влажности?
как на клиенте понять, что после 5 термо идут данные с других сенсоров?
добавлять еще по служебному байту "тип сенсора" на каждый сенсор? тогда распухнет этот пакет данных из-за служебной инфы.
как это по нормальному делается то? ведь я чувствую, что пытаюсь изобрести велосипед..
Непременно распухнет. А как иначе? Должна быть или жесткая структура метрик или каждая передаваемая метрика должна описываться типом и id.
тогда распухнет этот пакет данных из-за служебной инфы.
он у вас в первую очередь распух от неправильно выбранного типа данных. Вы не ответили на вопрос, зачем вам флоат, для температуры более чем достаточно типа int16_t, а для влажности - даже uint8_t. и сразу пакет похудеет в 2-3 раза
тогда распухнет этот пакет данных из-за служебной инфы.
он у вас в первую очередь распух от неправильно выбранного типа данных. Вы не ответили на вопрос, зачем вам флоат, для температуры более чем достаточно типа int16_t, а для влажности - даже uint8_t. и сразу пакет похудеет в 2-3 раза
int16_t - это ведь целочисленный формат, не так ли?
но вот что еще - как быть если в каком то сервере будет всего 10 термосенсоров == 40 байт
а в другом сервере будет тоже 40 байт, но данные будут распределены, например 5 термо и 5 датчиков влажности?
Изначально так задача не ставилась, Вы бы весь список хотелок озвучили сразу.
В таком случае я бы задался вопросом: а сколько у меня реально различных пакетов данных. Допустим, 20. Я бы описал 20 структур (это ничего не стоит по ресурсам исполнения) и первым полем передавал бы не длину, а ID структуры. По этому ID создавал бы нужную структуру и вычитывал бы её.
Ну здесь вы не правы. Сначала передаётся длина, а потом ID пакета. Но можно создать оберточную структуру в которой в начале ID получателя. Тогда остальные забют на приём этого пакета.
Непременно распухнет. А как иначе? Должна быть или жесткая структура метрик или каждая передаваемая метрика должна описываться типом и id.
а упаковать все ID в байтик не вариант? но проще конечно побитово, 4 байта - 32 датчика
int16_t - это ведь целочисленный формат, не так ли?
да, и что? вы не в курсе, как в целочисленном формате передавать температуру с одним или двумя знаками после запятой?
почему обязательно в этом порядке? если длина однозначно определяется ID - а часто это так и есть - длину можно и не передавать вовсе
но некоторые серверы имеют разное кол-вол термосенсоров и, например, есть или нет лазерный сенсор и так далее..
Значить, передавай с каждого сервера строку типа
ID T1NN T5NN H2NN L3NN
и разбирай ее на своем устройстве
ID это идентификатор сервера с которого пришла информация
T1NN, T5NN - показания температуры (Т) с даччика номер 1 и 5, NN - сопсно температура
H2NN - показания влажности (H) с даччика номер 2 NN - сама влажность
L3NN показания с лазерного даччика (L) номер 3, значение NN
Значить, передавай с каждого сервера строку типа
зачем же ты ему каку советуешь? ну нафига строки? пусть передает 1 байт - ID датчика, и дальше за ним - числовое значение.
Конечно пакеты распухают. А то будет как со слоненком. Нёс обезьяне привет и не донес. Чем больше бумаги, тем чище попа. Это и здесь работает. Если на прикладной уровне на длину можно забить, то на траспортном уже забиваю на содержание. Там важны длина данных, от кого, кому, id посылки, время отправки.
зачем же ты ему каку советуешь? ну нафига строки?
их передавать можно разной длины и потом разбирать легче.
вы это про ардуино пишете или так, вообще?
Для справки - все обсуждаемые в этой ветке поля - длина пакета и ID - находятся в сегменте данных пакета и никакой "транспортный уровень" эту длину в работе все равно не использует.
зачем же ты ему каку советуешь? ну нафига строки? пусть передает 1 байт - ID датчика, и дальше за ним - числовое значение.
Вот смари. Если формат пакета жестко задан и длина его известна, то при потере/неисправности одного/нескольких даччиков нам все равно придется передавать хоть какие-то значения, даже неверные,но при этом еще как-то информировать сборщика, что некоторые данные неверны, а при переменной длине пакета никто не мешает передаччику, если он обнаружил сбой даччика, информацию с него не передавать. Один раз не передаст, второй, а потом есть повод задумаца, а чойта у нас на сервере информации с одного/нескольких даччиков уже час/сутки нету? Не пора ли отправить туда юнгу/огнемётчиков, чтоб посмотрели/приняли меры.
В любом случае, я не настаиваю, это ж просто один из вариантов. Лично мне проще строку разобрать. :)
Лично мне проще строку разобрать. :)
так это тебе :) а у новичков при разборе строк вечно ТАКОЕ получается... как у вчерашнего кадра, у которого код для разбора 78 параметров занимал 2500 строк :)
В любом случае, я не настаиваю, это ж просто один из вариантов. Лично мне проще строку разобрать. :)
небось тоже свой интерпретатор писал? )))
ну акей, убедили.
небось тоже свой интерпретатор писал? )))
какрас, в процессе. Скоро выложу, для Леонарды.
Этот меня занозил
http://arduino.ru/forum/ishchu-ispolnitelya/simulyator-myshiatmega32u4-leonardo-due-nuzhen-sketch
ну акей, убедили.
ты Дед колись, написал интерпретатор али нет
ну акей, убедили.
ты Дед колись, написал интерпретатор али нет
ты #22 читал?
вы это про ардуино пишете или так, вообще?
Это для всего. В любой Ардуине для решения этой задачи должен быть код некой прикладной программы и код некого приемопередатчика. Это две независимые части взаимодествующие между собой и решающую общую задачу. А то что сейчас вы говорите это венегрет глюкнутых решений и потом на отладке будут проблемы--чего так глюкнуто не работает.
Ммм
ну акей, убедили.
ты Дед колись, написал интерпретатор али нет
ты #22 читал?
пока писал ты ответил, прочитал, ждёмс, я правда не знаю, оно мне нужно?
Сейчас сульфатацию в новых аккумуляторах снимаю да бесперебойники починяю, осталось три )))
int16_t - это ведь целочисленный формат, не так ли?
да, и что? вы не в курсе, как в целочисленном формате передавать температуру с одним или двумя знаками после запятой?
нет, не вкурсе. поэтому использую float.
короче пока вот прикрутил такую структуру:
вроде передаю-принимаю норм..
только вот, конечно, не очень то оно отличается от простого array of float...
и если на сервере термосенсоров всего 5, то данные о температуре остальных 5 будут приходить с нулями и не хочется их выводить на экран..
а может просто добавить еще одно поле - кол-во термосенсоров? и на клиенте проверять его и соответственно выводить только данные из этого кол-ва?
а может просто добавить еще одно поле - кол-во термосенсоров? и на клиенте проверять его и соответственно выводить только данные из этого кол-ва?
Ну, Вам же уже говорили, не только не выводить лишнее, но и не передавать и не принимать!
Только Вы это как-то "через зад" сделали. Действительно - у Вас просто массив, нахрена какая-то структура?
вы не в курсе, как в целочисленном формате передавать температуру с одним или двумя знаками после запятой?
нет, не вкурсе. поэтому использую float.
ну неужели сами не догадались
34.56 градуса домножаете на 100 = получаете целое 3456. Формат int16_t позволит хранить температуры от -325 до +325 градусов
Ровно точно таже храните свои напряжения VCC и Vbat
Такой подход позволит не только уменьшить размер данных при передаче - если применить его по всей программе, вы существенно уменьшите размер кода и сделаете его быстрее, потому что тип float на микроконтроллерах требует больших библиотек и очень медленный.
Ну, Вам же уже говорили, не только не выводить лишнее, но и не передавать и не принимать!
Только Вы это как-то "через зад" сделали. Действительно - у Вас просто массив, нахрена какая-то структура?
ну а как мне на одном и том же клиенте принимать данные от сервера с 5 и от сервера с 10 сенсорами?
я вижу только один вариант - в коде на клиенте иметь переменную, куда приходят данные из радиомодуля == максимального размера, то есть рассчитанную на получение данных от сервера с 10 сенсорами.
и тогда если получу от сервера с 5, просто в начале проверю поле с кол-вом сенсором и не буду выводить
t6 =0
t7 =0
както так..
ну и по структуре тоже согласен.. разве что она тут удобнее, так как есть разного типа данные.
наверное дальнейшая оптимизация такого пакета данных уже подразумевает гораздо лучшее знание языка и опыт.
не догадались
34.56 градуса домножаете на 100 = получаете целое 3456. Формат int16_t позволит хранить температуры от -325 до +325 градусов
Ровно точно таже храните свои напряжения VCC и Vbat
Такой подход позволит не только уменьшить размер данных при передаче - если применить его по всей программе, вы существенно уменьшите размер кода и сделаете его быстрее, потому что тип float на микроконтроллерах требует больших библиотек и очень медленный.
хм
интересно. спасибо. и получив на клиенте 3456, просто делю на 100 и уже вижу точку в нужном месте.
интересно. спасибо. и получив на клиенте 3456, просто делю на 100 и уже вижу точку в нужном месте.
не надо делить, а то вы снова получите тип float. Если вы используете данные в расчетах -так и используйте умноженные на 100, сделав нужные поправки в формуле. А если выводите на экран - то выводите сначала ЦЕЛОЕ T/100 - для этого случая это будет 34. а потом опять же ЦЕЛОЕ T%100 - это будет 56
Ну, если не хотите связываться с динамическим выделением, то да. Но лишнего не нужно ни пересывать, ни принимать.
Я уже говорил Вам, что нужно расписать разные структуры для разных источников. Если хотите статическую память, то сложить их друг на друга физически. Прочитали id поняли о какой структуре речь и её полностью вычитываете и показываете.
спасибо всем.
сделал struct, все пашет как надо - 100 байт летает по радио
и с помощью NUM_OF_TS могу указать на сервере нужное кол-во сенсоров
от float пока не ушел, думаю позже доделаю)
Не хватает ещё одного поля.
Не хватает ещё одного поля.
все поля на месте
CRC нет.
Неприличными словами не выражацца!
Не хватает ещё одного поля.