Очередной "Умный дом", на этот раз модульная система...

MaksVV
Offline
Зарегистрирован: 06.08.2015

sadman41 пишет:
Или только он и участвует.
Не, в обмене полезными данными он участвовать не будет. Физический адрес только для служебных сообщений и диагностики. 

sadman41 пишет:
Конечно, тут возникает вопрос - а как искать конкретный проблемный датчик в сети, если у них адреса одинаковые (находятся в одной области)...
 

нифига адреса не будут одинаковые, часть адреса (помещение и тип параметра) да, одинаковая будет, а вторая часть (номер датчика) - будет отличаться. 

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

можно кстати "адрес отправителя" разделить по нибблам. Левый - номер помещения, правый - тип контроллера. Хватит 15 комнат и 15 типов контроллеров? 

Лучше адреса не трогать. 255 адресов не очень много. У с учетом маршрутизации (я у себя modbus, bee и пр. сети пробрасываю через CAN)

Кстати по уровням абстракции 

https://mklimenko.github.io/russian/2018/05/13/a-guide-to-better-embedded-ru/

https://dic.academic.ru/dic.nsf/ruwiki/1659006

riv
Offline
Зарегистрирован: 20.07.2017

sadman41 пишет:
Мне кажется, чтобы байты туда-сюда не трусить, неплохо было бы начать с реальных сценариев управления. Тогда будет понятно, сколько типов контроллеров действительно необходимо.

Я как раз начал реализовывать этот слой, привязываю конкретные устройства к контроллерам.

Кстати нубский вопрос.

В библиотеке https://github.com/graynet-dev/aHomeBus есть главный класс 

class AHB

к нему указателем через виртуальный класс привязываю разные интерфейсы (CAN, Modbus ....)

class AHB_CAN : public AHB_COMM

к нему же (AHB) привязываю в зависимости от типа узла классы 

class AHB_MASTER
class AHB_SLAVE
class AHB_NODE

Все классы привязываются из основного скетча 

#include "ahb.h"
uint8_t can_addr_net[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,77,78};
int size_can_addr_net = sizeof(can_addr_net)/sizeof(can_addr_net[0]);
uint8_t uart_addr_net[] = {0,55,56};
int size_uart_addr_net = sizeof(uart_addr_net)/sizeof(uart_addr_net[0]);
uint8_t modbus_rtu_addr_net[] = {100,101,102,103};
int size_modbus_rtu_addr_net = sizeof(modbus_rtu_addr_net)/sizeof(modbus_rtu_addr_net[0]);
AHB ahb0(0,100,Node);
AHB_NODE ahbNode0(0);
AHB_CAN ahbCan0(53, CAN_250KBPS, MCP_8MHZ , 2,can_addr_net, size_can_addr_net);
AHB_UART ahbUart0(Serial,uart_addr_net,size_uart_addr_net);
AHB_MODBUS_RTU ahbModBusRtu0(0,1,10,modbus_rtu_addr_net, size_modbus_rtu_addr_net);
void setup() {
  Serial.begin(115200);
  Serial.print(F("AHB Node - "));
  Serial.println(ahb0._nodeId);
  delay(200*ahb0._nodeId);
  ahb0.begin();
  Serial.print(F("Attach CAN..."));if(ahb0.busAttach(&ahbCan0) < 0) {Serial.println(F("Error!"));}else{Serial.println(F("Done!"));}
  Serial.print(F("Attach Node logic..."));if(!ahb0.nodeAttach(&ahbNode0) < 0) {Serial.println(F("Error!"));}else{Serial.println(F("Done!"));}
  Serial.print(F("Attach Node sender to main route..."));if(!ahbNode0.nodeBusAttach(&ahb0) < 0) {Serial.println(F("Error!"));}else{Serial.println(F("Done!"));}
  Serial.print(F("Attach UART..."));if(ahb0.busAttach(&ahbUart0) < 0) {Serial.println(F("Error!"));}else{Serial.println(F("Done!"));
  Serial.print(F("Attach MODBUS_RTU..."));if(ahb0.busAttach(&ahbModBusRtu0) < 0) {Serial.println(F("Error!"));}else{Serial.println(F("Done!"));
}

А вот из класса AHB_NODE хочу вызвать класс из чужой библиотеки.

#include "Adafruit_BME280.h"

Вроде делаю все по науке

Объявляю в public  ahn_node.h

Adafruit_BME280 bme;

Создаю экземпляр класса в конструкторе

AHB_NODE::AHB_NODE(uint8_t id){
  bme = new Adafruit_BME280();
} 

Указываю параметры класса в 

byte AHB_NODE::begin() {
  bme.begin(0x76, &Wire);
}

Класс создается но данные с датчика не идут

    bme.takeForcedMeasurement();
    Serial.print("Temperature = ");
    Serial.print(bme.readTemperature());
    Serial.println(" *C");

 Есть мысли?

sadman41
Offline
Зарегистрирован: 19.10.2016

Без реального ahn_node.h и реализации методов можно долго фантазировать, что не так сделано.

Мне кажется, что в реальности создаётся два истанса bme - через дефолтовый конструктор класса и, дополнительный, через new(). Это плохо, нужно что-то одно выбирать Но, с одного данные всё равно должны идти... если присоединение верное, выставлен правильный адрес BME и Wire.h кикстартнуто.  Напишите маленький класс для отладки - я прогоню у себя, если не разберётесь по ходу пьесы.

riv
Offline
Зарегистрирован: 20.07.2017

sadman41 пишет:
Весь топик я не читал, может зайду на очередной круг... Я так понял, что концептуально контролируется некая условная точка в пространстве (дома) например. Т.е. важно знать, что в кладовке перегрев крупы... Важно ли при этом знать какая нода (тип) с какими наборами датчиков находится в этой кладовой? Наверное, нет. Достаточно, чтобы метрики были привязаны ко времени измерения и его точке. Таким образом - нода, при посылке данных (или коллектор метрик) должна всего лишь оперировать адресом и набором метрик, которые она способна породить. Например, в кладовке с адресом N стоит нода и отсылает метрику “температура“. Нужна влажность - добавляем ноду с адресом N, отсылающую метрику "влажность". Если есть желание - совмещаем ноды в одном устройстве с адресом N, которое отсылает обе метрики. Нужно работать по запросу - коллектор шлёт команду "отчитаться точке N", ноды опознают свой адрес (один и тот же), отчитываются разными метриками. Т.е. железо на нижнем уровне модифицируется и комбинируется как угодно, на протокольном же изменений не требуется.

Тут вот какое дело, Макс поправляй если мыслишь иначе, изначально предполагалось и к этому мы идем, что сеть буде иметь свои мозги хотя бы на минимальном уровне и выполнять определенные функции и сценарии сама. Например контроль температуры, влажности, вентиляции в помещении, используя для этого несколько разных сенсоров, возможно от разных контроллеров и управляя различными устройствами с разных контроллеров, и для решения этой задачи не понадобится управляющий компьютер. Задача управляющего компа это интерфейс и интеграция с доп системами, например той же алисой, мультирумом, почтой, погодой из вне и пр. 

В то же время для того же интерфейса нужно видеть температуры, а при наличии датчиков пол, потолок, окна, температура радиатора, входной выходной коллектор вентиляции, за бортом и их тоже.

Так что должны быть как ручное управление, выключить вентиляцию, так и автомат, держи CO2 на 600.

riv
Offline
Зарегистрирован: 20.07.2017

sadman41 пишет:

Без реального ahn_node.h и реализации методов можно долго фантазировать, что не так сделано.

Мне кажется, что в реальности создаётся два истанса bme - через дефолтовый конструктор класса и, дополнительный, через new(). Это плохо, нужно что-то одно выбирать Но, с одного данные всё равно должны идти... если присоединение верное, выставлен правильный адрес BME и Wire.h кикстартнуто.  Напишите маленький класс для отладки - я прогоню у себя, если не разберётесь по ходу пьесы.

Так либа то вся тут https://github.com/graynet-dev/aHomeBus

https://github.com/graynet-dev/aHomeBus/blob/master/ahb_node.h

https://github.com/graynet-dev/aHomeBus/blob/master/ahb_node.cpp

если убираю в объявлении ругается что не знает что такое bme

если не делаю new выпадает в процессе выполнения когда доходит до вызова.

Я могу из скетча вызвать как и все остальное, но будет очень криво. Хотел все в либе спрятать.

 

sadman41
Offline
Зарегистрирован: 19.10.2016

riv пишет:

если убираю в объявлении ругается что не знает что такое bme

если не делаю new выпадает в процессе выполнения когда доходит до вызова.

Я могу из скетча вызвать как и все остальное, но будет очень криво. Хотел все в либе спрятать.

new() возвращает в bme указатель, но сама переменная bme объявлена не как указатель. Я в ООП не сильно шарю, не знаю какие спецэффекты бывают, если в ссылку на класс указатель бахнуть, но всё же начал с того, что объявил бы bme как указатель (с *)

А вообще - тут нужен небольшой класс. Разобраться, почему сенсор не заводится в большом проекте - не очень просто. В моём, к примеру, Wire создаётся и стартует только если есть вкомпилированная поддержка I2C сенсоров. Ну и я частенько забывают имплементируемый сенсор в список I2C-устройств добавлять. Обнаруживаю это через полчаса траха с "неработающим датчиком", который отдельно работает.

UPD: адафрутовский begin возвращает код успеха - можно к нему прицепиться и узнать насчёт работы BME в принципе. Или в init() натыкать сериалов - узнать на чём спотыкается.

riv
Offline
Зарегистрирован: 20.07.2017

Переобъявил как указатель 

Adafruit_BME280 *bme;

убрал new  и вызываю

byte AHB_NODE::begin() {
 
  bme->begin(0x76, &Wire);
}
void AHB_NODE::bme280_print(void) {

    bme->takeForcedMeasurement();
    Serial.print("Temperature = ");
    Serial.print(bme->readTemperature());
    Serial.println(" *C");

    Serial.print("Pressure = ");

    Serial.print(bme->readPressure() / 100.0F);
    Serial.println(" hPa");

    Serial.print("Approx. Altitude = ");
    Serial.print(bme->readAltitude(SEALEVELPRESSURE_HPA));
    Serial.println(" m");

    Serial.print("Humidity = ");
    Serial.print(bme->readHumidity());
    Serial.println(" %");

    Serial.println();
  
}

Та же песня. То же в скетче работает.

sadman41
Offline
Зарегистрирован: 19.10.2016

Друг. Выбери что-то одно - или инстанс класса без new() или указатель на класс и new().

riv
Offline
Зарегистрирован: 20.07.2017

sadman41 пишет:

Друг. Выбери что-то одно - или инстанс класса без new() или указатель на класс и new().

Да все перепробовал, поэтому и извращаюсь, если как ты говоришь, то возвращает 0 в обоих вариантах, я с этого начал.

Сейчас пытаюсь отлаживаться уже глубже.

riv
Offline
Зарегистрирован: 20.07.2017

В общем научным тыком завел.

Выходит, что 

byte AHB_NODE::begin() {
bme.begin(0x76, &Wire);
}

Не отрабатывает

Запихнул сюда

void AHB_NODE::bme280_print(void) {

    if (! bme.begin(0x76, &Wire))
    {
    Serial.println("BME ERROR");
    }
    else
    {
    Serial.println("BME OK");
    }
    
    
    
    bme.takeForcedMeasurement();
    Serial.print("Temperature = ");
    Serial.print(bme.readTemperature());
    Serial.println(" *C");

    Serial.print("Pressure = ");

    Serial.print(bme.readPressure() / 100.0F);
    Serial.println(" hPa");

    Serial.print("Approx. Altitude = ");
    Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
    Serial.println(" m");

    Serial.print("Humidity = ");
    Serial.print(bme.readHumidity());
    Serial.println(" %");

    Serial.println();
  
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Может на момент выполнения ahb_node.begin() wire ещё не запущен? Попробуй рядом его подопнуть.

demid.net
Offline
Зарегистрирован: 02.12.2019

riv пишет:
  изначально предполагалось и к этому мы идем, что сеть буде иметь свои мозги хотя бы на минимальном уровне и выполнять определенные функции и сценарии сама. Например контроль температуры, влажности, вентиляции в помещении, используя для этого несколько разных сенсоров, возможно от разных контроллеров и управляя различными устройствами с разных контроллеров, и для решения этой задачи не понадобится управляющий компьютер. Задача управляющего компа это интерфейс и интеграция с доп системами, например той же алисой, мультирумом, почтой, погодой из вне и пр. 

В то же время для того же интерфейса нужно видеть температуры, а при наличии датчиков пол, потолок, окна, температура радиатора, входной выходной коллектор вентиляции, за бортом и их тоже.

Так что должны быть как ручное управление, выключить вентиляцию, так и автомат, держи CO2 на 600.

Вот да, примерно так :) Народ, а есть какое-то текстовое/табличное/графическое описание того, что написано на С ? Язык программирования это просто способ записи алгоритма. Сам алгоритм-то есть ?

Я мозг сломал с этими железками. Отопление/свет/розетки работают и хорош. Пока отложил остальное.

Когда начинал думал примерно так:

Вот есть у меня "блок реле". На нем МК с каном и (внезапно) реле 6шт. Тупо делю id на 4 почти равные части. Называю их "тип блока", "номер блока", "тип параметра", "номер параметра". Значения параметров передаю уже в данных пакета. 

"Блок реле" тип 0x01, номер блока 0x01. Тип параметра "реле" 0x01, номер параметра 0x01-0x06.

Причем 0x00 в типе блока автоматом означает "все блоки" и имеет наибольший приоритет. Равно как одной командой 0x01 0x00 0x01 0x00 можно включить/выключить все реле на всех блоках "реле" в системе.

Дальше у меня есть блок "температура" тип 0x02, номер 0x01. На нем 6 каналов 1-wire. По аналогии можно одной командой запросить температуру со всех блоков и всех каналов.

Теперь мне нужно или третье устройство, в котором я пропишу что есть блок реле и блок температуры и водружу в него логику работы например "термостат" чтобы он запрашивал температуру в одном блоке и рулил реле на другом. Это ничем не будет отличаться от централизованных систем со всеми их геморроями и кан тут не нужен от слова совсем. Уже на этом этапе можно взять любую из готовых систем, прописать свои блоки и вуаля... Или эту логику повесить на какой-то из этих же существующих блоков. Может на оба сразу для надежности. По сути виртуальный блок "термостат", состоящий из 1 (или нескольких) каналов температуры и 1 (или нескольких) реле. Вот на этом этапе я и застрял. Ибо логика у всех разная. Разорвал сеть на несколько сегментов и завел интерфейсный модуль с вайфаем, которой заканчивается эта микросеть реле-температура. Он и рулит всей логикой. Но тут меня осенило, что микроконтроллеру абсолютно пофигу что вы подключили к реле и где меряете температуру. А по-моему вся логика должна строиться на том, что МК знает что конкретно к нему подключено. То есть помимо низкого уровня "блок"-"канал", нужен еще высокий, где можно указать что вот к этому каналу блока температуры подключен уличный датчик температуры. И вот тут умный дом должен знать, что регулировать эту температуру не возможно. И запрос в сеть должен выглядеть как "температура на улице" а не 0x02 0x01 0x01 0x06. Вы сами можете не помнить к какому блоку и в какой канал этот датчик воткнут, а он работает и выдает температуру на улице. Сущностей в квартире/доме не так много как кажется. Их можно все перечислить и называть вещи своими именами а не настраивать gpio по сети. Так часть логики переедет в тот блок, где его основной параметр. То есть если к блоку реле номер 1 к каналу номер 2 подключен холодильник, то сам блок принимает команды "подключить холодильник" и "отключить холодильник". Это всё что можно с ним сделать. И сам блок реле в данном случае знает, что если "никого нет", то холодильник отключать нельзя. А телевизор например можно. Сомневаюсь что у кого-то по-другому. Как обычно сумбурно, много букв... Сори.

riv
Offline
Зарегистрирован: 20.07.2017

sadman41 пишет:
Может на момент выполнения ahb_node.begin() wire ещё не запущен? Попробуй рядом его подопнуть.

Слушай а вариант, у меня много чего заводится. Проект большой...

Спасибо. А то уже не знал куда рыть.

MaksVV
Offline
Зарегистрирован: 06.08.2015

demid.net пишет:
Вот да, примерно так :) Народ, а есть какое-то текстовое/табличное/графическое описание того, что написано на С ? Язык программирования это просто способ записи алгоритма. Сам алгоритм-то есть ?

тут

MaksVV
Offline
Зарегистрирован: 06.08.2015

demid.net пишет:
Сущностей в квартире/доме не так много как кажется. Их можно все перечислить и называть вещи своими именами а не настраивать gpio по сети.

такой дорогой и идём, не понимаю, почему все кто сюда заходит, думают обратное. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

riv пишет:
Лучше адреса не трогать. 255 адресов не очень много. У с учетом маршрутизации (я у себя modbus, bee и пр. сети пробрасываю через CAN)

а какая проблема если раздробить адрес на комнаты? с учётом того, что адрес конечного элемента по факту тройной получается:  4бит *8бит*8бит. Тут уж за миллион переваливает, мало? 

по-моему такие одинаковые адреса (см. ниже) как то нелепо выглядят, дублирование какое-то идёт.

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

riv пишет:
Лучше адреса не трогать. 255 адресов не очень много. У с учетом маршрутизации (я у себя modbus, bee и пр. сети пробрасываю через CAN)

а какая проблема если раздробить адрес на комнаты? с учётом того, что адрес конечного элемента по факту тройной получается:  4бит *8бит*8бит. Тут уж за миллион переваливает, мало? 

по-моему такие одинаковые адреса (см. ниже) как то нелепо выглядят, дублирование какое-то идёт.

Наши ноды да но повторюсь Modbus имеет жесткую адресацию, и для меня 255 и так мало. Названия не важны, важно количество адресуемых уникальных ID.

Это мои реально используемые адреса и их будет больше

uint8_t can_addr_net[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,77,78};
int size_can_addr_net = sizeof(can_addr_net)/sizeof(can_addr_net[0]);

uint8_t uart_addr_net[] = {0,55,56};
int size_uart_addr_net = sizeof(uart_addr_net)/sizeof(uart_addr_net[0]);


uint8_t modbus_rtu_addr_net[] = {100,101,102,103};
int size_modbus_rtu_addr_net = sizeof(modbus_rtu_addr_net)/sizeof(modbus_rtu_addr_net[0]);

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

сделай "тип сообщения" - шлюз. "подтипы" - модбас, bee, uart и т.д. И в этих типах сообщений разряд, где должен стоять адрес CAN узла, будет восприниматься как совсем другая адресация - адресация твоих пробросов от других протоколов. и отдавай хоть все 255 на это дело. 

Т.е. в зависимости от типа сообщения может меняться не только структура payload , но и младших разрядов ID. 

Я вообще не понимаю нафига так сильно усложнять протокол. С CANом то бы разобраться, а тут уже и модбасы и  уарты и радиоканалы пошли - повеситься легче. Вся эта шляпа ассортишная без глюков работать точно не будет. CAN в работе ещё не был. Тут только с ним ошибок в реальных условиях ещё выявлять и выявлять. Если уж надо будет CAN с другими сетями сопрячь - шлюз можно отдельно построить, но до этого далеко. 

 

riv
Offline
Зарегистрирован: 20.07.2017

К меня уже межинтрефейсный маршрутизатор написан. При изменении адреса придется почти пол библиотеки переписывать. И я честно говоря не совсем понял зачем менять адресацию. У нас 3 нибла есть msgtype и devtype. Куда больше то?

demid.net
Offline
Зарегистрирован: 02.12.2019

MaksVV пишет:

demid.net пишет:
Сущностей в квартире/доме не так много как кажется. Их можно все перечислить и называть вещи своими именами а не настраивать gpio по сети.

такой дорогой и идём, не понимаю, почему все кто сюда заходит, думают обратное. 

За всех не отвечу, но меня сбило обилие других слов типа модбас, зигби и.т.п :) Конечно сразу мысль "какой-то универсальный протокол, соединяющий всё со всем". Тогда у меня только один вопрос: логику где хранить ?

riv
Offline
Зарегистрирован: 20.07.2017

Смотри либу в библиотеке на github. Основной класс ahb. Есть абстракция типа tcp/ip поверх всего железа. Есть виртуальный класс ahb_comm, который определяет функции дочерних классов уже протоколов нижнего уровня. Т.е из главного класса отправка во все шины (протоколы) идёт в одном формате. Если интересно могу как Макс написать мануал. Но только на выходных. Общая инфа есть тут https://github.com/graynet-dev/aHomeBus но это скорее мой блог и хранилище кода. Программную документацию потом буду писать.

MaksVV
Offline
Зарегистрирован: 06.08.2015

riv пишет:
И я честно говоря не совсем понял зачем менять адресацию. У нас 3 нибла есть msgtype и devtype. Куда больше то?

Ты ещё забыл про номер датчика. как раз больше не надо. Я наоборот хочу меньше. Я хочу это сделать для более рационального использования адресного пространства без дублирования. Оптимизировать то бишь. Так меньшее количество адресов потребуется. 

Вот смотри два разных подхода на примере. Имеем допустим две комнаты: зал и спальню. Нужно по шине подключить три выключателя света, три розетки в зале и по два в спальне; ну и узел подсветки пола, например, какого-нибудь в зале.  (розетки и выключатели просто для примера , вместо них могут быть любые сенсоры и ИУ однотипные). То что это, в какой-то степени, идиотизм каждую розетку и выключатель подключать через  локальный МК по CAN шине - дело десятое. Речь сейчас про принцип. (А иногда всё таки так удобнее чтобы проводов меньше тянуть). 

Вариант 1 . Ниже выполнение поставленной задачи на алгоритме, который сейчас. 

Адреса узлов:  зал_розетка1, зал_розетка2, зал_розетка3, зал_выключатель1, зал_выключатель2, зал_выключатель3, зал_подсветка_пола,  спальня_розетка1, спальня_розетка2, спальня_выключатель1, спальня_выключатель2. 

Типы параметров: зал_Выключатель1, зал_Выключатель2, зал_Выключатель3, спальня_Выключатель1, спальня_Выключатель2. 

Типы девайсов: зал_Розетка1, зал_Розетка2, зал_Розетка3, спальня_Розетка1, спальня_Розетка2, зал_светПлинтус. 

При обращении к розетке_1 в зале будет такая цепочка. зал_розетка1->зал_Розетка1-> номер датчика 1.  При обращении сверху тебе важен объект - например выключатель, а не узел, к которому он подключен.  Но ты обязан пройти через адрес узла (который к слову лишний тут получается). В данном варианте два раза в адресах указывается адрес помещения и два раза тип сенсора -и в адресе узла, и в адресе параметра. Точно также и с ИУ. Обращение к розетке -  адрес помещения и тип ИУ присутствует и в адресе узла, и в адресе девайса. Вот тебе дублирование и съедание адресного пространства понапрасну.  Для исключения этого мы вроде ввели понятие "тип параметра" и "номера датчиков", но это работает, когда в помещении единственный узел и всё подключено к нему. Если же и в пределах одного помещения идёт разделение функционала по узлам, то такой фокус не прокатывает и приходится кучу лишних адресов добавлять, а "номер датчика" не используется и будет везде = 1. 

Вариант 2 . Как я хочу сделать. 

Адреса помещений:  зал, спальня. 

Типы параметров: выключатель 

Типы девайсов: розетка, светПлинтус. 

А номера розеток и выключателей на узлах конфигурируются через  "номер датчика". Всё! Надо обратиться к розетке  3 в зале? Пожалуйста:   зал -> розетка -> номер датчика 3.  При этом все узлы одной комнаты обрабатывают CAN сообщения, адресованные этой комнате. 

Чувствуешь разницу? Т.е. понемногу мы приходим к одной из фишек CAN шины, что идентификатор обозначает не физ узел, а объект данных. 

UPD. мы можем и не дробить адрес узла на RoomAddr и PhysAddr. А просто оставить RoomAddr полноценный 8 битный. Т.е. в полезных данных CAN обмена в идентификаторе полностью будет отсутствовать информация с какого физического узла исходит CAN сообщение (только RoomAddr).  PhysAddr будет фигурировать в составе ID только в служебных CAN сообщениях (heartbeat, nodeguard, reboot и т.д.), например на месте разряда dev_type, т.к. служебные CAN сообщения призваны работать именно с физическим железом.

Вот и уровни абстракции появляются. RoomAddr - это некий виртуальный узел помещения, состоящий из одного или нескольких физических узлов. 

riv
Offline
Зарегистрирован: 20.07.2017

Честно говоря я не думаю что мы умнее разработчиков canopen, devicenet и пр. разработчиков протоколов Овер Кан. Они адреса источника и получателя в id вставили. Правда в device net 7 бит вроде и 127 адресов.

riv
Offline
Зарегистрирован: 20.07.2017

Думаю от 256 адресов отправитель и 256 получатель уходить не стоит. Остальные биты можно объединить это 13 бит итого 2 в 13 это 8192 адреса/параметра/устройства. Либо оставить как есть. Делать только получателя по ID не понимая кто запросил, зачем и имеет ли он на это право, потерять маршрутизацию в сопрягаемые сети думаю не стоит.

demid.net
Offline
Зарегистрирован: 02.12.2019

MaksVV пишет:

Чувствуешь разницу? Т.е. понемногу мы приходим к одной из фишек CAN шины, что идентификатор обозначает не физ узел, а объект данных. 

riv пишет:

 Делать только получателя по ID не понимая кто запросил, зачем и имеет ли он на это право, потерять маршрутизацию в сопрягаемые сети думаю не стоит.

Посмотрите на CAN-шину не как на интерфейс для связи различных контроллеров, а именно как на ШИНУ данных. Вы же когда вызываете функцию по работе, например, i2c, вы же не передаете ей в качестве аргумента имя функции, ее вызывающую ? И уж тем более не получаете в ответ имя функции, которая отработала вызов с целью проверки, а имела ли она право обрабатывать то, что я ей послал... Если смотреть на CAN как на один большой (просто распределенный) контроллер - жить станет проще. Да, нужна некая диагностика узлов на предмет их онлайности и правильности работы, но в остальном это один МК в созможностью добавления ножек в любой момент.

riv
Offline
Зарегистрирован: 20.07.2017

demid.net пишет:

Посмотрите на CAN-шину не как на интерфейс для связи различных контроллеров, а именно как на ШИНУ данных. Вы же когда вызываете функцию по работе, например, i2c, вы же не передаете ей в качестве аргумента имя функции, ее вызывающую ? И уж тем более не получаете в ответ имя функции, которая отработала вызов с целью проверки, а имела ли она право обрабатывать то, что я ей послал... Если смотреть на CAN как на один большой (просто распределенный) контроллер - жить станет проще. Да, нужна некая диагностика узлов на предмет их онлайности и правильности работы, но в остальном это один МК в созможностью добавления ножек в любой момент.

Если был один CAN, готов был бы наверное согласиться, но у меня CAN это хребет вокруг которого крутится сеть Modbus (контроллер температуры, жалюзи), UART ... которые хочу однозначно адресовать с центрального шлюза и сервера Majordomo.

Так вот эта сеть сейчас для меня прозрачна. Я отправляя команду формата описанного выше у Макса (привелся к его формату) попадаю на нужный мне адрес не зависимо от платформы и протокола. Причем каждый узел может иметь и по 2-3 интерфейса CAN со своей адресацией, НО диапазон адресов от 1 до 255, и узел получив пакет смотрит к нему или нет, если нет то не к сети ли подключенной к нему на другом его интерфейсе. Причем за счет абстракции роутеру плевать что там CAN или Modbus или TCP/IP. Приводись к любой физике или каналу, важно умей отправить то что тебе кинули в нужную шину ну и принять из нее.

Я все протоколы привожу к виртуальному вызову

Так CAN реализован


bool AHB_CAN::ahbSend_V(uint8_t type, uint8_t dev_type, uint8_t target, uint8_t msg_type, uint8_t source,  uint8_t len, byte data[8]) {
        uint32_t addr = ahbCanAddrAssemble(type, dev_type, target, msg_type, source);
        if(addr == 0){ 
          return false;
        }
        
        lastErr = _interface.sendMsgBuf(addr, 1, len, data);
        if(lastErr != CAN_OK) {
          return false;
        }

        return true;
}

Так пока Modbus (руки не дошли транслятор сделать)

bool AHB_MODBUS_RTU::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source,  uint8_t len, byte data[8]){
       //Serial.println("Send Modbus_RTU");
        // Разбираем ввод и формируем телеграмму
        //type
        //cmd
        //port
        //data[8]
        //Из них тянем данные
        //source куда вернуть ответ при приеме
  telegram[0].u8id = target;//Slaves; // slave address
  telegram[0].u8fct = 3; // function code (this one is registers read)
  telegram[0].u16RegAdd = 0; // start address in slave
  telegram[0].u16CoilsNo = 11; // number of elements (coils or registers) to read
  telegram[0].au16reg = au16data; // pointer to a memory array in the Arduino        
        if (!_interface.query(telegram[0])){//если 0 т.е нормальная отправка
          //1. Установить флаг что была отправка и можно начать поллинг
          send_modbus_rtu=true;
          modbus_rtu_request_sender=source;
        }

}

Так UART

bool AHB_UART::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source,  uint8_t len, byte data[8]){
            
        byte tlen = 0;
        _interface->write(0x01);
        _interface->print(type,HEX);
        _interface->write(0x1F);
        _interface->print(target,HEX);
        _interface->write(0x1F);
        _interface->print(source,HEX);
        _interface->write(0x1F);
        if(port > 0) {
            _interface->print(port,HEX);
        }else{
            //Arduino print internally casts to double :(
            _interface->print(F("FF"));
        }
        _interface->write(0x1F);
        _interface->print(len,HEX);

        _interface->write(0x02);
        if(len > 0) {
            for(tlen = 0; tlen < len; tlen++) {
                _interface->print(data[tlen], HEX);
                _interface->write(0x1F);
            }
        }
        _interface->write(0x04);
        _interface->println();
        return true;
}

Это интеграция с Majordomo

bool AHB_GW_CAN_TO_OKBIT::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source,  uint8_t len, byte data[8]){
      //uint16_t type_gw;
      //type_gw = 8000+source;
      //this->build(2, 4, 8004, 13, 0, 0, 5, 6, 1, 4);
      this->build(target,source+target*100, 8000+source, cmd, 0, 0, 1, 1, target, source);     
      _interface.beginPacket(_interface.remoteIP(), _interface.remotePort());
      _interface.write(replyGate);
      _interface.endPacket();  

       //uint32_t rxId = 0x80000000;
       //rxId = (type & 0xFFFFFFFF)<<28 | (cmd & 0xFFFFFFFF)<<20 | (target & 0xFFFFFFFF)<<12 | (port & 0xFFFFFFFF)<<8 | source ;
       //sprintf(buffer, "ID: %.8lX  Data: %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X\n\r",
       //       rxId, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
       //Serial.print("Okbit ");Serial.print(dest_gw_can_to_okbit);Serial.print(":");Serial.println(remPort_okbit);             
     
}

Это отправка по UDP

bool AHB_GW_CAN_TO_UDP::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source,  uint8_t len, byte data[8]){
       uint32_t rxId = 0x80000000;
       rxId = (type & 0xFFFFFFFF)<<28 | (cmd & 0xFFFFFFFF)<<20 | (target & 0xFFFFFFFF)<<12 | (port & 0xFFFFFFFF)<<8 | source ;
       sprintf(buffer, "ID: %.8lX  Data: %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X\n\r",
              rxId, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
       //Serial.print("UDP ");Serial.print(dest_gw_can_to_udp);Serial.print(":");Serial.println(remPort);       
      _interface.beginPacket(dest_gw_can_to_udp, remPort);
      _interface.write(buffer); //
      _interface.endPacket();
      
}

А вот отправка из центрального класса

byte AHB::ahbSend(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source, byte len, byte data[8]) { //7 Моя логика
        bool state,broadcast_route=false;
        byte errors=0,i;
        signed char busId_route;
        if(source == 0) source = _nodeId;
        busId_route=-1;

        //Определяем в какую шину кидать пакет
        for(signed char busId=0; busId<AHB_BUSNUM; busId++) {
          //Проверяем что шина подключена
          //Serial.println("!"); //_busAddr[busId]->address_network_get(0)
          if (_busAddr[busId] != 0x00){
          
            //Если target broadcast и broadcast есть в этой сети то кидаем туда            
            if (target==_busAddr[busId]->address_network_get(0)){
                broadcast_route=true;
                #ifdef AHB_DEBUG
                  Serial.print(F("TX Route target -  "));Serial.print(target);Serial.print(F(" to Bus - "));
                  Serial.print(busId);  Serial.print(F(" Form source - "));Serial.println(source);
                #endif //AHB_DEBUG
                //Отправка в шину busId
                state = _busAddr[busId]->ahbSend_V(type, cmd, target,  port, source, len, data);
                //Отправка в очередь сообщений с busId  
                //////state = ahbAddSendMsgQueue(type, cmd, target, port, source, len, data, busId);
                if(!state) errors++;                     
            }
            
            //Пробегаем по таблице маршрутов сети
            for (int i=0; i<_busAddr[busId]->net_size_get();i++){
              //Если получатель в сети 
              if (target==_busAddr[busId]->address_network_get(i)&&_busAddr[busId]->address_network_get(i)!=0){
                #ifdef AHB_DEBUG
                  Serial.print(F("Target ")); Serial.print(target); Serial.print(F(" locate to bus ")); Serial.println(busId);
                #endif //AHB_DEBUG
                busId_route=busId;
              }
            }
          }
        }
        
        if(busId_route!=-1){
          if(_busAddr[busId_route] != 0x00){
             #ifdef AHB_DEBUG
              Serial.print(F("TX Route target - "));Serial.print(target);Serial.print(F(" to Bus - "));
              Serial.print(busId_route); Serial.print(F(" Form source - "));Serial.println(source);
             #endif //AHB_DEBUG
             //Отправка в шину busId_route
             state = _busAddr[busId_route]->ahbSend_V(type, cmd, target,  port, source, len, data);
             
             //Отправка в очередь сообщений с busId_route   
             //////state = ahbAddSendMsgQueue(type, cmd, target, port, source, len, data, busId_route);
             if(!state) errors++;          
          }
        }
        else{
          if(!broadcast_route) {
            //#ifdef AHB_DEBUG
            Serial.print(F("TX No route for target - ")); Serial.print(target);
            Serial.print(F(" NOT Send !!!!"));  Serial.print(F(" Form source - "));Serial.println(source);
            //#endif //AHB_DEBUG
          }
        }
        return errors;
}

При сборке скетча я прописываю физ интерфейсы и указываю какие адреса за этим интерфейсом и свой адрес.

В итоге я могу даже не знать в какой шине адрес. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

riv пишет:
Честно говоря я не думаю что мы умнее разработчиков canopen, devicenet и пр. разработчиков протоколов Овер Кан. Они адреса источника и получателя в id вставили.

riv пишет:
Думаю от 256 адресов отправитель и 256 получатель уходить не стоит. .....Делать только получателя по ID не понимая кто запросил, зачем и имеет ли он на это право, потерять маршрутизацию в сопрягаемые сети думаю не стоит.

дак я и предлагаю 256 оставить. Почему не понимая, кто запросил? RoomAddr отправителя то будет присутствовать в ID. Т.е. адрес и отправителя и получателя так и остаётся в ID. Только вот какая тебе разница какой физический узел измерил температуру в комнате, тебе должно быть важно что это за температура  - пола, радиатора или воздуха (объект) и в какой именно комнате (локация).  

Я не понимаю, как у тебя происходит маршрутизация между разными сетями, да и вообще плохо в этом разбираюсь, но можно пойти на компромисс и просто зарезервировать часть адресов под "виртуальные узлы". Т.е. если нам нужно более одного узла в комнате - создаём в диапазоне виртуальных соответствующий виртуальный (как бы объединяя несколько железных узлов в один виртуальный. При этом настраиваем в фильтре CAN приёмника у всех этих железных узлов пропускать адрес этого виртуального узла, чтобы они все сообщения принимали как один узел).  Это очень похоже на рейд массив "страйп" в компе. Часть данных может быть на одном физическом диске,  другая часть - на другом. Но винде пофиг - для неё оба физ.диска это один раздел. Винда работает с разделом.  Так же и у нас, железный адрес как бы не особо нужен, только для диагностики. Сверху не важно какой физический узел замерил температуру, главное откуда эта температура (раздел диска). А если тебе нужен прям стопудовый узел с железным адресом, к которому другие интерфейсы подключены, заносишь его в диапазон "железных" узлов и у него RoomAddr будет совпадать с PhysAddr.

По тому, в каком диапазоне адресов узел находится, отличать будем  - виртуальный узел или железный. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Про какие-то уровни абстракции вроде говорили, чтобы наш протокол был универсальный, не зависящий от железа.  А тебе зачем-то "пробросы" других интерфейсов через CAN нужно стало делать с какими то определёнными адресами.  Что там, жалюзи у тебя по модбасу? Почему нельзя было сконфигурировать на узле девайс жалюзи в массиве девайсов?  В наш протокол сверху мы говорим (по адресу: комната->девайс жалюзи->№окна ) в рамках нашего протокола "открыть", "закрыть" шторы, там не знаю, состояние положения штор можем запросить - всё в рамках нашего протокола. И, раз мы договорились абстракцию взаимодействия с девайсами сделать, то жалюзи на узле будут управляться через функцию прокладку, которая и будет переводить формат команд и параметров нашего протокола в модбас. вот и всё! Если надо с мажордомо управлять, а, насколько я понял, с ним проще взаимодействовать по езернету, то так же делаем через узел-шлюз. Мажордомо <->Езернет <->узел-шлюз<->нашCANпротокол<->функция прокладка<->модбас<->жалюзи.

А ты собрался всё и вся чтоли в протокол добавить? А если что-нибудь забудешь добавить или устройство тебе понадобится подключить с какой нибудь экзотической шиной (например Dali , KNX, DMX512), всё,  весь протокол переписывать?  Какая же это универсальность?

Как там в CANopen? словарь объектов? Объекты это же наши сенсоры (массив parameter) и ИУ (массив девайсов). Дак всё-же может и будем с объектами взаимодействовать? 

НЕ надо сверху взаимодействовать с физическими узлами! Надо взаимодействовать с объектами (сенсоры, ИУ)! НЕ надо напрямую адресовать сверху до узла! НЕ надо взаимодействовать сверху с узлом через (сквозь) наш протокол! Надо взаимодействовать сверху с нашим протоколом! А наш протокол уже будет взаимодействовать с объектом. Сверху должно быть похеру что там на конце модбас или зигбии Сверху все лишь просто нужно обращаться как мы и задумывали: локация->объект(тип объекта)->конкретный экземпляр. Если хочется наш протокол подготовить для подключения каких-то стандартных вещей, то имхо, нужно просто написать различные функции-прокладки для этих стандартных вещей (Датчики даллас, модбасы и т.д. и т.п.).  А ты, получается, не шлюзуешь данные других протоколов, а пробрасываешь их через наш, получается ломая некоторые изначальные принципы нашей адресации. Ты все адреса к одному байту привел. Нафига мы тогда добавили тип параметра (тип девайса), да ещё и номера датчиков (твоя же идея кстати)? Ты щас их не используешь, получается, адресуя свои жалюзи только в общем первом (одном) байте.  Конечно тебе 255 не хватает.  А если у тебя жалюзи такие в нескольких комнатах? Адресовать будешь:   Жалюзи_комната1, Жалюзи_комната2. ?  Хреновасто.  Надо чётко разделять локацию и объект, а у тебя всё в одном.

Если узлы находятся в одной комнате, то разряд адреса локация у них должен быть один и тот же. 

Короче для меня картина "правильного" протокола понемногу проясняется. Знаю теперь как двигаться дальше.  

riv
Offline
Зарегистрирован: 20.07.2017

Предложи структуру ID c описанием. Что копья ломать. Подробно про роутинг к выходным отвечу.

riv
Offline
Зарегистрирован: 20.07.2017

Думал ты хочешь оставить всего 16 адресов в сети. Ты говорил выше про нибл. И хочешь убрать адрес отправителя.
Если остаётся байт получателя и байт отправителя то все остальное на твое усмотрение.
По поводу modbus, у меня ещё мультисплит а это уже сложное устройство.Его датчиком или реле не представишь. И.е если у устройства на модбасе есть свои мозги я хочу с ним работать по адресу.

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

И, раз мы договорились абстракцию взаимодействия с девайсами сделать, то жалюзи на узле будут управляться через функцию прокладку, которая и будет переводить формат команд и параметров нашего протокола в модбас. вот и всё! Если надо с мажордомо управлять, а, насколько я понял, с ним проще взаимодействовать по езернету, то так же делаем через узел-шлюз. Мажордомо <->Езернет <->узел-шлюз<->нашCANпротокол<->функция прокладка<->модбас<->жалюзи.

А ты собрался всё и вся чтоли в протокол добавить? А если что-нибудь забудешь добавить или устройство тебе понадобится подключить с какой нибудь экзотической шиной (например Dali , KNX, DMX512), всё,  весь протокол переписывать?  Какая же это универсальность?

Похоже мы говорим об одном и том же но на разных языках. Посмотри выше мой код. Я все это уже реализовал.

Но, ты рассчитываешь на одно устройство на одном RS485 интерфейсе а я на N устройств. 

Мало того если нужен новый протокол я его просто реализую отдельным интерфейсом.

Смотри внимательно

Так CAN реализован

01 bool AHB_CAN::ahbSend_V(uint8_t type, uint8_t dev_type, uint8_t target, uint8_t msg_type, uint8_t source,  uint8_t len, byte data[8]) {

Так пока Modbus (руки не дошли транслятор сделать)

01 bool AHB_MODBUS_RTU::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source,  uint8_t len, byte data[8]){

Так UART

01 bool AHB_UART::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source,  uint8_t len, byte data[8]){

Это интеграция с Majordomo

01 bool AHB_GW_CAN_TO_OKBIT::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source,  uint8_t len, byte data[8]){

Это отправка по UDP

01 bool AHB_GW_CAN_TO_UDP::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source,  uint8_t len, byte data[8]){

А теперь вуаля это вызов этих функций которые вытаскивает маршрутизатор по ID шины

_busAddr[busId_route]->ahbSend_V(type, cmd, target,  port, source, len, data);

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Я сначала так хотел (попилить адрес на нибблы). Но сказали 15 комнат мало. Тогда я решил 255 оставить, но имел ввиду что физический адрес контроллера в составе ID (для полезных CAN фреймов) будет отсутствовать. В служебных фреймах физ.адрес поместиться на место разряда dev-type. 

все таки сплит система это девайс - имхо.  Дак может быть в твою адресацию (маршрутизацию) можно добавить байт и привести к виду:  Локация -> девайс ?  Тогда тебе адресов будет норм хватать и логичнее всё будет. 

Интересно про сложность работы с мультисплитом. Какое-то сверху приложение уже готовое чтоли есть, или модуль в мажордомо для данной сплит системы , раз нужно данные через CAN неизменно в модбас прокидывать?  Почему его нельзя представить сенсором и девайсом?  просто хочу понять случаи , где может затаиться засада с моим подходом. 

 

riv
Offline
Зарегистрирован: 20.07.2017

.

riv
Offline
Зарегистрирован: 20.07.2017

Повторюсь, если оставляешь под адресацию устройств 256 отправителю и 256 получателю, то оставшиеся 13 бит пользуй как считаешь нужным. Я от 256 железных устройств в мультипротокольной сети не уйду.

Мало того к каждому узлу с CAN может быть подключено несколько сегментов CAN и других интерфейсов.

А вот датчики уже ниже.

Виртуалить на уровне сети а не на уровне PC считаю утопией. Про поиск неисправности думал? Отказал датчик № 3 в комнате с 10 контроллерами, подключенными к неизвестно какому узлу. А может контроллер отказал и ли провод отпаялся и или код сбойнул или ...

Не. Я слишком хорошо знаю что такое РВР и поиск неисправности. Как диагностировать железо? А ПО? А физ. линии?

Просто прикинь что у тебя в машине есть датчики под капотом 1-10, 11-20 в салоне и 21-30 в багажнике. Подключенные к 3, 6 и 2 контроллерам соответственно. Причем датчик 1,15, 25 отвечают за топливную систему. И вот прикинь у тебя сбой и машина не заводится. А схемы кроме логической нет. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

riv пишет:
Похоже мы говорим об одном и том же но на разных языках. Посмотри выше мой код. Я все это уже реализовал.

Но, ты рассчитываешь на одно устройство на одном RS485 интерфейсе а я на N устройств.

Почему одно? Несколько вот так подключать

MaksVV
Offline
Зарегистрирован: 06.08.2015

riv пишет:
Про поиск неисправности думал? Отказал датчик № 3 в комнате с 10 контроллерами, подключенными к неизвестно какому узлу. А может контроллер отказал и ли провод отпаялся и или код сбойнул или ...

Не. Я слишком хорошо знаю что такое РВР и поиск неисправности. Как диагностировать железо? А ПО? А физ. линии?

Диагностировать точно также как ты это делаешь. Только по физ. адресам. Куда подключен датчик? - смотреть это можно в конфигурации. Диагностическую систему нужно развивать. Можно тип команд специальный придумать, чтоб конфигу в кан МК выбрасывали по команде. 

riv
Offline
Зарегистрирован: 20.07.2017

Кроме того я могу легко перекинуть модбас и би местами на разных контроллерах. Просто поднять интерфейс , прописать маршруты и вперед. А вот если будет уникальная логика на узле то все сливай воду. Перелей прошивку перепрограммируй.

Я хочу иметь одинаковые контроллеры, с разъемом переходником (типа шилды ардуино монтажные или под винт) к которым подключаются нужные ИУ и сенсоры и интерфейсные контроллеры и единый софт для НОД. Отличие настройки, адрес и подключенное оборудование. Все как в начале темы. Универсальность и заменяемость полная. Зашел с PC (лучше с WEB) через шлюз по CAN на контроллер, выбрал из списка датчики, привязал их к пинам, указал сценеарий там или еще что, указал соседей куда что потправлять.

Включил и работает. А если конфиг еще на сервере держать то сбойный контроллер просто из ЗИПа поменял, подключил, по чему то типа TFTP (логически естественно) загрузил конфиг и вуаля. 

Маршрутизатор работает как просто как топор, пришел пакет узлу смотрим если это мне в обработку или если узлу подключенному ко мне по другой шине, то ретрансляция, если не так то игнор.

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

riv пишет:
Про поиск неисправности думал? Отказал датчик № 3 в комнате с 10 контроллерами, подключенными к неизвестно какому узлу. А может контроллер отказал и ли провод отпаялся и или код сбойнул или ...

Не. Я слишком хорошо знаю что такое РВР и поиск неисправности. Как диагностировать железо? А ПО? А физ. линии?

Диагностировать точно также как ты это делаешь. Только по физ. адресам. Куда подключен датчик? - смотреть в можно в конфигурации. Диагностическую систему нужно развивать. Можно тип команд специальный придумать, чтоб конфигу в кан МК выбрасывали по команде. 

Программно диагностировать неисправную систему? Не понимая глючтит софт который и выдает ошибки или физика или ИУ. Это адский труд. 

Поверь на слово не усложняй. Виртуальный контроллер лучше делать на мощной машине сверху.

 

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

riv пишет:
Похоже мы говорим об одном и том же но на разных языках. Посмотри выше мой код. Я все это уже реализовал.

Но, ты рассчитываешь на одно устройство на одном RS485 интерфейсе а я на N устройств.

Почему одно? Несколько вот так подключать

pin 14, 15, 9 это адреса в модбасе или физ пины?

MaksVV
Offline
Зарегистрирован: 06.08.2015

"пин ардуино" столбец тут не используется. Он остался от начальной задумки, где девайсы рулились только по GPIO. 

riv
Offline
Зарегистрирован: 20.07.2017

Виртуалить датчики и ИУ в пределах контроллера стоит. Если хочешь виртуалить в пределах комнат и/или систем для сценариев или виртуальных систем то это отдельный слой. Т.е скрыть физ пины от протокола наверное стоит. А вот датчики и устройства нет

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

"пин ардуино" столбец тут не используется. Он остался от начальной задумки, где девайсы рулились только по GPIO. 

И все же как обращаться к Node 10, 11, C в моей схеме. Или например как обеспечить обмен Node 11 c 22, шлюзом и PC.

MaksVV
Offline
Зарегистрирован: 06.08.2015

riv пишет:
Программно диагностировать неисправную систему?

а ты как собрался свою диагностировать?  В моей все отличие, что комнатах где более одного узла, полезные CAN сообщения не имеют в ID физ. адреса узла. Но это диагностится по служебным CAN фреймам, сердцебиение узла и т.д. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

riv пишет:
И все же как обращаться к Node 10, 11, C в моей схеме. Или например как обеспечить обмен Node 11 c 22, шлюзом и PC.

Дак говорю надо обращаться не к нодам, а к объектам. Какие объекты у тебя на этих нодах присутствуют? Свет на кухне, например.    Kitchen-> lamp_ceil_onoff_d -> #1 .  А что есть обмен ?

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

riv пишет:
Программно диагностировать неисправную систему?

а ты как собрался свою диагностировать?  В моей все отличие, что комнатах где более одного узла, полезные CAN сообщения не имеют в ID физ. адреса узла. Но это диагностится по служебным CAN фреймам, сердцебиение узла и т.д. 

На шлюзе или PC контролирую параметры (вернее их выход за диапазон и/или их нестандартное например резкое изменение) и четко понимаю, что на контроллере 7, ага его имя node_7_Hallway_main, ага это главный контроллер в щите коридора, неправильно выдается состояние датчика или съем информации со счетчика.

Самое простое замена из ЗИП на другой.

Не помогло. Смотрю что с подключенным устройством. Тоже замена из ЗИП.

Не помогло. Звоним физику.

Все лаконично и понятно. По схеме Э4 отрабатываем (Схема электрическая соединений Э4).

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

riv пишет:
И все же как обращаться к Node 10, 11, C в моей схеме. Или например как обеспечить обмен Node 11 c 22, шлюзом и PC.

Дак говорю надо обращаться не к нодам, а к объектам. Какие объекты у тебя на этих нодах присутствуют? Свет на кухне, например.    Kitchen-> lamp_ceil_onoff_d -> #1 .  А что есть обмен ?

Я готов на объекты, даже считаю их обязательными, но без отказа от прямой адресации к датчику/устройству.

Мало того считаю что и вирт объекты нужны но поверх этих слоев.

Например климат система это комбинация привода радиатора, кондея, нагревателя вентсистемы. Контроль температуры с разных датчиков. Сценарии и пр.

riv
Offline
Зарегистрирован: 20.07.2017

Давай все же отработаем сначала структуру ID  и уровни абстракции (уровни виртуализации). Я всю следующую неделю дома. Вот и поработаем удаленно ;-)

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

riv пишет:
И все же как обращаться к Node 10, 11, C в моей схеме. Или например как обеспечить обмен Node 11 c 22, шлюзом и PC.

Дак говорю надо обращаться не к нодам, а к объектам. Какие объекты у тебя на этих нодах присутствуют? Свет на кухне, например.    Kitchen-> lamp_ceil_onoff_d -> #1 .  А что есть обмен ?

Ну у объекта есть свойства, методы и события. У меня пока нет объектов я только роутер добил а теперь наоборот нижний уровень добиваю. А вот потом займусь прослойкой. Только помоделировать надо.

Обмен это как раз для виртуальных устройств. Обмен данными 11 например сенсор CO2 а 22 это контроллер вентиляции. (это условно, могут быть мульти функц. устройства с кучей датчиков и иу, которые для тебя черный ящик только с протоколом управления и датчиками и иу)

Я хочу и на сервере их видеть и ими управлять в ручном режиме но и пусть они сами трудятся в автоматическом режиме.

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

ок, у нас системы разного уровня. У тебя прям ЦУП, а у меня так,  лампочками по шине помигать. Поэтому и подходы разные , трудно прийти к общему знаменателю.