Думаю, что в такой системе стоило бы залимитить границы такта. А то подвиснет передача и сигналка будет бесконечно ждать.
В общем разобрался в чем дело было. Я при иницировании тактирования (то есть состояние ждем спада линии RX) не учел условие , что надо это делать только при отсутствии передачи. И когда начинал передачу, сигналка отвечала тактированием, что логично , но мой скетч ошибочно это воспринимал как будто она хочет начать передачу и врубал своё тактирование , которое накладывалось на передачу, короче каша мяша была. Добавил это условие (строка 77) и всё заработало. Друзья, протокол хакнут! Сигналка с охраны снимается /ставится. На команды реагирует.
Вот рабочий тестовый скетч . Потом допилю, привязку модуля к сигналке и обработку ответов от сигналки (где лежит состояние охраны, двери , капот и т.д.)
#define RX 3
#define TX 2
volatile bool dataRX[80] = {0}; // буфер приема данных от сигналки
enum statesRX {WAIT, CLOCK}; // возможные статусы приемника
volatile bool stateRX = WAIT ; // переменная статуса приемника
volatile bool printFlag = 0; // флаг распечатки приемного буфера в отладку
volatile byte dataTX[10]= {0}; // буфер передачи данных на сигналку (пакет байт команды)
enum statesTX {WAIT_FALL, PROPUSK, TXbyCLOCK, TXin1}; //возможные статусы передатчика
volatile byte stateTX = WAIT_FALL ; // переменная статуса передатчика
enum comastates {NUL, OHR_ON, OHR_OFF}; // статусы передачи пакетов команды управления сигналкой
volatile byte comastat = 0; // переменная статуса передачи пакетов команды управления сигналкой
byte SL_key[2]={0x58, 0x61}; // байты ключа сигнализации
bool Timer_waitCLOCKING_by_Starline = 0;
uint32_t prev_waitCLOCKING_by_Starline = 0;
#define CLOCK_ON TCCR2B=2
#define CLOCK_OFF TCCR2B=0
void setup() {
pinMode (TX, OUTPUT); // линию TX на выход
digitalWrite (TX, 1); // и ставим в busIdle
pinMode (RX, INPUT_PULLUP); // линию RX на вход с подтяжкой
Serial.begin(250000);
//---------настройка таймера2 для выполнения нами тактирования передачи от сигналки (обработчик выскочит раз в 100мкс).
TCCR2A = 2 ;
TCCR2B = 0;
OCR2A = 198; // установка регистра совпадения (100 мкс для прескалера 8)
TIMSK2 = 2; // разрешить прерывание по таймеру по сравнению A
//TCCR2B = 2; // включ таймер раз в 100мкс
//-----------------------------------------------------------------------
}
void loop() {
if (stateTX==TXin1){delayMicroseconds(100); digitalWrite(TX,1);stateTX=WAIT_FALL;}
if (Timer_waitCLOCKING_by_Starline && millis()- prev_waitCLOCKING_by_Starline>300)
{
Timer_waitCLOCKING_by_Starline=0;
digitalWrite(TX,1);
stateTX=WAIT_FALL;
}
//--------------------иницирование отправки команд на сигналку через терминал
if (Serial.available())
{
Serial.println();
byte inbyte = Serial.read();
if (inbyte == 'z') {Serial.println (F(" Send SMS Zapros Sostoyanya: ")); Send_To_Starline (0x42);}
else if (inbyte == 'o') {Serial.println (F(" Ignition OFF"));}
else if (inbyte == 'i') {Serial.println(F(" Ignition ON"));}
else if (inbyte == '1') {Serial.println (F(" Send SMS Ohrana ON: ")); Send_To_Starline (0x42); comastat = OHR_ON; }
else if (inbyte == '0') {Serial.println (F(" Send SMS Ohrana OFF: ")); Send_To_Starline (0x42); comastat = OHR_OFF;}
}
//--------------------------------------------------------------------------------------------
//---------------------распечатка в терминал буфера приемника, при получении сообщения от сигналки
if (printFlag){
byte B[3] = {0};
Serial.print ("Starline: ");
byte CS = 0 ;
for (int i=0; i<10; i++) {
byte A= 0;
for (int b = 0 ; b<8; b++){bitWrite(A, b, dataRX[(8*i)+b]);}
if (i<9)CS+=A;
if (A<=0xF)Serial.print("0"); Serial.print(A, HEX); Serial.print(" ");
if (i==9) {Serial.print(" CS is "); if (CS==A) {
Serial.println("OK!");
if (comastat ==OHR_ON) {comastat =0; Send_To_Starline (0x11);}
else if (comastat ==OHR_OFF){comastat =0; Send_To_Starline (0x10);}
}
else Serial.println("Error!!!"); }
}
printFlag = 0 ; Serial.println();
}
//------------------------------------------------------------------------------
//---------контроль линии приемника на предмет спада (если увидели спад, значит сигналка хочет передавать)
bool curRX = digitalRead(RX);
static bool lastRX = curRX;
if (stateTX==WAIT_FALL && stateRX == WAIT && lastRX != curRX) // если статус приемника и передатчика "ждем спад" и состояние линии RX изменилось
{
if (lastRX && !curRX){ // если на пине RX спад
stateRX = CLOCK;
delayMicroseconds (100);
if (bool((1 << 3) & PIND)) return; // если было ложное срабатывание пина, выходим.
digitalWrite (TX,0); // короткий строб в ноль, всё по осциллограмме
delayMicroseconds (40);
CLOCK_ON; // включаем тактирование для оппонента.
}
lastRX = curRX;
}
//-------------------------------------------------------------
}
ISR(TIMER2_COMPA_vect) // обработчик вылазит раз в 100мкс, тактируем для сигналки
{
static byte bitNumber = 0 ;
if (bitNumber > 0) {dataRX[bitNumber-1]= bool((1 << 3) & PIND);} // читаем очередной бит (начиная со второго прерывания)
PORTD ^= (1 << 2); // тактируем, изменив состояние пина TX на противоположное
if (bitNumber==80) {bitNumber=0; stateRX = WAIT; printFlag = 1; CLOCK_OFF;return;}
bitNumber++;
}
void Send_To_Starline(byte SLcommand){
if (stateRX == CLOCK) {delay (200);}
dataTX[0]=0x0A;
dataTX[1]=millis();
dataTX[2]=(dataTX[1]^SLcommand)^SL_key[0];
dataTX[3]=(dataTX[1]^SLcommand)^SL_key[1];
dataTX[4]=0xFF;
byte CS = 0 ;
for (byte i=0; i<5;i++) {CS+=dataTX[i];}
dataTX[9]=CS;
Serial.println(); Serial.print (" Send to Starline:");
for (byte i=0; i<10;i++) {if (dataTX[i]<=0xF)Serial.print("0"); Serial.print(dataTX[i], HEX); Serial.print(" ");}
Serial.println();
PORTD &=~(1 << 2); // садим в 0 линию передачи , инициируя желание передавать данные
Timer_waitCLOCKING_by_Starline = 1; prev_waitCLOCKING_by_Starline = millis();
attachInterrupt(1, RX_CLOCK, FALLING); // и ждем тактирования от сигналки (принимать тактирование будет внеш прерывание)
}
void RX_CLOCK () { // обработчик внешнего прерывания, выступает как приёмник тактирования от сигналки для выполнения нашей ей передачки.
static byte bitNumberTX = 0 ;
static byte byteNumberTX = 0 ;
if (stateTX==WAIT_FALL){stateTX=PROPUSK; detachInterrupt(1); attachInterrupt(1, RX_CLOCK, CHANGE);return;} // выполняется только когда FALLING
//--------------ниже передача команды на шину по тактированию от сигналки-----------
else if (stateTX==PROPUSK){stateTX=TXbyCLOCK;}
else if (stateTX==TXbyCLOCK){
if (bool((1 << (bitNumberTX)) & dataTX[byteNumberTX])) {PORTD |=(1 << 2); } // читаем очередной бит из команды
else {PORTD &=~(1 << 2); } // и выставляем его на пине TX
// Serial.print(bool((1 << (bitNumberTX)) & dataTX[byteNumberTX]));
//----------------------------------------------------------------------------------
if (byteNumberTX==9 && bitNumberTX == 7) // если все 80 бит переданы, выходим , сбросив переменные и откл внеш прерывание
{
stateTX=TXin1;
detachInterrupt(1);
bitNumberTX=0; byteNumberTX=0;
return;
}
bitNumberTX++; if (bitNumberTX == 8) {bitNumberTX = 0 ;byteNumberTX++;}
}
}
Поздравляю! Хорошая работа! Молодость однако )))
спасибо.
Отчитываюсь, допилил! Надеюсь кому-то , кроме меня, это будет полезно. Скетч:
#include <EEPROM.h>
#define RX 3 // пин ардуино, к которому подключать линию RX GSM (не менять!)
#define TX 2 // пин ардуино, к которому подключать линию TX GSM
#define DEBUG // раскомментировать, если нужна отладка в терминал. Закомментировать эту строку, когда вставляете эту городьбу в свой проект)
volatile byte dataRX[10] = {0}; // буфер приема данных от сигналки
enum statesRX {WAIT_FALL, WAITSTROB, CLOCKING_DETECTED}; // возможные состояния приемника
volatile byte stateRX = WAIT_FALL ; // переменная состояния приемника
volatile byte bitNumberRX = 0 ;
volatile byte byteNumberRX = 0 ;
volatile bool SLmessage_received = 0; // флаг что принято новое сообщение от сигналки
volatile byte dataTX[10]= {0}; // буфер передачи данных на сигналку (пакет байт команды)
enum statesTX {WAIT_CLOCKING, PROPUSK, TXbyCLOCK, TXtoIDLE}; //возможные состояния передатчика
volatile byte stateTX = WAIT_CLOCKING ; // переменная состояния передатчика
volatile byte bitNumberTX = 0 ;
volatile byte byteNumberTX = 0 ;
byte SL_key[2]={0}; // байты ключа сигнализации
// таймеры возврата в bus-Idle в случае неответов от сигналки
bool Timer_waitCLOCKING_from_Starline = 0;
uint32_t prev_waitCLOCKING_from_Starline = 0;
enum protectTimer_states {TIMER_OFF, TIMER_WAIT_RESPONSE, TIMER_PROTECT, TIMER_LASTSTATE};
byte Timer_waitRESPONSE_from_Starline = 0;
uint32_t prev_waitRESPONSE_from_Starline = 0;
byte Timer_needRepeat = 0;
uint32_t prev_timer_needRepeat = 0;
bool needPropusk = 0 ;
byte RepeatCommand = 0 ;
byte CountRepeat = 0 ;
#define CLOCK_ON TCCR2B=2
#define CLOCK_OFF TCCR2B=0
#define SEND_CLOCKING_AND_READ_BITS ISR(TIMER2_COMPA_vect)
const uint8_t ZAPROS = 0x42;
const uint8_t START_ENG = 0x21;
const uint8_t STOP_ENG = 0x20;
const uint8_t OHRANA_ON = 0x11;
const uint8_t OHRANA_OFF = 0x10;
bool Doors = 0 ;
bool Locks = 0 ;
bool Ohrana = 0 ;
bool Trunk = 0 ;
bool Hood = 0 ;
bool Ignition = 0 ;
bool Brake = 0 ;
bool Engine = 0 ;
bool Trevoga = 0 ;
bool Tiltsensor = 0 ;
bool Shocksensor = 0 ;
void setup() {
pinMode (TX, OUTPUT); // линию TX на выход
digitalWrite (TX, 1); // и ставим в busIdle
pinMode (RX, INPUT_PULLUP); // линию RX на вход с подтяжкой
#ifdef DEBUG
Serial.begin(115200); Serial.println(); Serial.println(F("Arduino Restart"));
Serial.print(F("Starline Key: "));
#endif
for (byte i=0; i<2; i++)
{
SL_key[i] = EEPROM.read(i+200);
#ifdef DEBUG
if (SL_key[i]<0xF){Serial.print("0");} Serial.print(SL_key[i], HEX); Serial.print(F(" "));
#endif
}
#ifdef DEBUG
Serial.println();
#endif
//---------настройка таймера2 для выполнения нами тактирования передачи от сигналки (обработчик выскочит раз в 100мкс).
TCCR2A = 2 ;
TCCR2B = 0;
OCR2A = 198; // установка регистра совпадения (100 мкс для прескалера 8)
TIMSK2 = 2; // разрешить прерывание по таймеру2 по сравнению A
//TCCR2B = 2; // включ таймер раз в 100мкс
}
void loop()
{
SL_Data(); // работа протокола SL_DATA
}
void SL_Data()
{
//таймеры сброса тактирования или сброса линии TX при передаче в случае неответов от оппонента
timers_to_protect_against_failures();
#ifdef DEBUG
//иницирование отправки команд на сигналку через терминал
Command_to_Starline_from_Terminal();
#endif
//обработка принятых сообщений от сигналки
processing_of_received_SLmessages();
//отправка сигнала тактирования на сигналку
send_CLOCKING_to_Starline();
}
void send_CLOCKING_to_Starline(){
if (Timer_waitRESPONSE_from_Starline!=TIMER_PROTECT){ // тактируем, если не включена защитная задержка глюков связи
bool curRX = digitalRead(RX);
static bool lastRX = curRX;
if (lastRX != curRX){ // если состояние линии RX изменилось
if (stateTX==WAIT_CLOCKING && stateRX == WAIT_FALL) // если статус приемника и передатчика "ждем спад"
{
if (lastRX && !curRX){ // если увидели спад на RX, значит сигналка хочет передавать, ниже отправляем ей тактирвание
stateRX = WAITSTROB;
delayMicroseconds (100);
if (bool((1 << 3) & PIND)) {stateRX = WAIT_FALL; return;} // если было ложное срабатывание RX пина, выходим.
//ниже включение таймера защиты от возможных глюков при неответах
if (Timer_waitRESPONSE_from_Starline==TIMER_OFF) {Timer_waitRESPONSE_from_Starline = TIMER_WAIT_RESPONSE; prev_waitRESPONSE_from_Starline = millis();}
digitalWrite (TX,0); // короткий строб в ноль, делаем всё по снифферской осциллограмме с ори обмена данными
delayMicroseconds (40); // длина строба
CLOCK_ON; // включаем тактирование для оппонента.
}
}
lastRX = curRX;
}
}
}
SEND_CLOCKING_AND_READ_BITS // обработчик вылазит раз в 100мкс, тактируем для сигналки и читаем очередной бит от неё
{
if (stateRX == WAITSTROB) {stateRX = CLOCKING_DETECTED; PORTD ^= (1 << 2);}
else if (stateRX == CLOCKING_DETECTED)
{
if (bool((1 << 3) & PIND)){dataRX[byteNumberRX]|= (1<<(bitNumberRX));}// читаем
else {dataRX[byteNumberRX]&=~(1<<(bitNumberRX));} // очередной бит
PORTD ^= (1 << 2); // тактируем, изменив состояние пина TX на противоположное
if (bitNumberRX==7 && byteNumberRX == 9) {endRX(); SLmessage_received = 1; return;} // сообщение полностью принято
bitNumberRX++; if (bitNumberRX==8){bitNumberRX=0; byteNumberRX++;} // рост счётчиков бит и байт
}
}
void endRX(){CLOCK_OFF; bitNumberRX=0; byteNumberRX=0; stateRX = WAIT_FALL;}
void processing_of_received_SLmessages()
{if (SLmessage_received){
#ifdef DEBUG
Serial.print ("Starline Response: ");
#endif
byte CS = 0 ;
for (int i=0; i<10; i++)
{
if (i<9)CS+=dataRX[i]; // подсчёт CS
#ifdef DEBUG
if (dataRX[i]<=0xF)Serial.print("0"); Serial.print(dataRX[i], HEX); Serial.print(" ");
#endif
if (i==9)
{
#ifdef DEBUG
Serial.print(" CS is ");
#endif
if (CS==dataRX[i]) // если получен валидный ответ от сигналки
{
Timer_waitCLOCKING_from_Starline = 0; // сбрасываем таймер ожидания тактирования от сигналки
Timer_waitRESPONSE_from_Starline = TIMER_OFF; // сбрасываем таймер ожидания ответа от сигналки
Timer_needRepeat = 0 ; CountRepeat = 0 ;
#ifdef DEBUG
Serial.println("OK! ");
#endif
if (dataRX[0]==0x0B && dataRX[4]==0x00) // принята процедура привязки GSM, запоминаем ключ Starline
{
Registration_SL_GSM();
#ifdef DEBUG
Serial.println(F("Registration GSM successfully completed!"));
#endif
}
else {
Doors = (bool((1 << 0) & dataRX[1]));
Trunk = (bool((1 << 2) & dataRX[1]));
Hood = (bool((1 << 3) & dataRX[1]));
Ignition = (bool((1 << 3) & dataRX[3]));
Brake = (bool((1 << 4) & dataRX[1]));
Locks = (bool((1 << 5) & dataRX[1]));
Ohrana = (bool((1 << 6) & dataRX[1]));
Trevoga = (bool((1 << 4) & dataRX[2]));
Shocksensor = (bool((1 << 1) & dataRX[5]));
Tiltsensor = (bool((1 << 0) & dataRX[6]));
#ifdef DEBUG
Serial.print (" Door: "); Serial.print (Doors); Serial.print (" Ign: "); Serial.print (Ignition);
Serial.print (" Brake: "); Serial.print (Brake); Serial.print (" Trunk: "); Serial.print (Trunk);
Serial.print (" Hood: "); Serial.print (Hood); Serial.print (" Locks: "); Serial.print (Locks);
Serial.print (" Ohrana: "); Serial.print (Ohrana); Serial.print (" Trevoga: "); Serial.print (Trevoga);
Serial.print (" Shock: "); Serial.print (Shocksensor); Serial.print (" Tilt: "); Serial.println (Tiltsensor);
#endif
}
}
else // Если CS неправильная
{
#ifdef DEBUG
Serial.println("Error!!!");
#endif
}
}
}
SLmessage_received = 0 ;
#ifdef DEBUG
Serial.println();
#endif
}
}
#ifdef DEBUG
void Command_to_Starline_from_Terminal() // инициирование отправки команд на сигналку с терминала
{
if (Serial.available())
{
Serial.println();
byte inbyte = Serial.read();
if (inbyte == 'z') {Serial.println (F(" Send SMS Zapros Sostoyanya: ")); Send_To_Starline (ZAPROS);}
else if (inbyte == '1') {Serial.println (F(" Send SMS Ohrana ON: ")); Send_To_Starline (OHRANA_ON);}
else if (inbyte == '0') {Serial.println (F(" Send SMS Ohrana OFF: ")); Send_To_Starline (OHRANA_OFF);}
else if (inbyte == 'r') {Serial.println (F(" GSM is reset! ")); Reset_SL_GSM(); }
else if (inbyte == 'p') {needPropusk=!needPropusk; Serial.print (F("Propusk ")); Serial.println (needPropusk);}
}
}
#endif
void Send_To_Starline(const byte &SLcommand) // процедура отправки команды на сигналку
{
if (stateRX > WAIT_FALL) {delay (200);}
RepeatCommand = SLcommand;
dataTX[0]=0x0A;
dataTX[1]=millis();
dataTX[2]=(dataTX[1]^SLcommand)^SL_key[0];
dataTX[3]=(dataTX[1]^SLcommand)^SL_key[1];
dataTX[4]=0xFF;
byte CS = 0 ;
for (byte i=0; i<5;i++) {CS+=dataTX[i];}
dataTX[9]=CS;
#ifdef DEBUG
Serial.print (" Send to Starline: ");
for (byte i=0; i<10;i++) {if (dataTX[i]<=0xF)Serial.print("0"); Serial.print(dataTX[i], HEX); Serial.print(" ");}
Serial.println();
#endif
PORTD &=~(1 << 2); // садим в 0 линию передачи , инициируя желание передавать данные
Timer_waitCLOCKING_from_Starline = 1; prev_waitCLOCKING_from_Starline = millis(); // включаем таймер защиты
Timer_needRepeat = 1; prev_timer_needRepeat = millis();
attachInterrupt(1, Accept_clocking_and_transmit_bits, FALLING); // и ждем тактирования от сигналки (принимать тактирование будет внеш прерывание)
}
void Accept_clocking_and_transmit_bits () //обработчик внешнего прерывания, выступает как приёмник тактирования от сигналки для выполнения нашей ей передачки.
{
if (stateTX==WAIT_CLOCKING){if (needPropusk) stateTX=PROPUSK; else stateTX=TXbyCLOCK; attachInterrupt(1, Accept_clocking_and_transmit_bits, CHANGE);return;}
//--------------ниже передача команды на шину по тактированию от сигналки-----------
else if (needPropusk && stateTX==PROPUSK){stateTX=TXbyCLOCK;}
else if (stateTX==TXbyCLOCK) // принимаем тактирование от сигналки и по нему отправляем побитно команду
{
if (bool((1 << (bitNumberTX)) & dataTX[byteNumberTX])) { PORTD |=(1 << 2); } // читаем очередной бит из команды
else {PORTD &=~(1 << 2); } // и выставляем его на пине TX
//----------------------------------------------------------------------------------
if (byteNumberTX==9 && bitNumberTX == 7) { endTX(); return;}// если все 80 бит переданы, выходим , сбросив переменные и откл внеш прерывание
bitNumberTX++; if (bitNumberTX == 8) {bitNumberTX = 0 ;byteNumberTX++;}
}
}
void endTX() {detachInterrupt(1); stateTX=TXtoIDLE; bitNumberTX=0; byteNumberTX=0;}
void timers_to_protect_against_failures()
{
if (stateTX==TXtoIDLE){delayMicroseconds(100); digitalWrite(TX,1);stateTX=WAIT_CLOCKING;}
if (Timer_waitCLOCKING_from_Starline && millis()- prev_waitCLOCKING_from_Starline>=200)
{
Timer_waitCLOCKING_from_Starline=0;
endTX();
}
if (Timer_needRepeat && millis() - prev_timer_needRepeat>=3500)
{
CountRepeat++; if (CountRepeat>=3) CountRepeat = 3 ;
Timer_needRepeat = 0 ;
needPropusk=!needPropusk;
if (CountRepeat<3){Send_To_Starline (RepeatCommand);}
}
if (Timer_waitRESPONSE_from_Starline>0 && millis() - prev_waitRESPONSE_from_Starline>=4000)
{
Timer_waitRESPONSE_from_Starline++;
if (Timer_waitRESPONSE_from_Starline==TIMER_PROTECT) {endRX(); digitalWrite(TX,1);}
else if (Timer_waitRESPONSE_from_Starline>=TIMER_LASTSTATE){Timer_waitRESPONSE_from_Starline = TIMER_OFF;}
prev_waitRESPONSE_from_Starline = millis();
}
}
void Reset_SL_GSM () {SL_key[0]=0xFF; SL_key[1]=0xFF; EEPROM.write(200,0xFF);EEPROM.write(201,0xFF);}
void Registration_SL_GSM () {SL_key[0]=dataRX[1]; SL_key[1]=dataRX[2]; EEPROM.write(200,dataRX[1]);EEPROM.write(201,dataRX[2]);}
ну и пример лога:
Arduino Restart
Starline Key: FF FF
отправляю запрос состояния с терминала
Send SMS Zapros Sostoyanya:
Send to Starline: 0A 91 2C 2C FF 00 00 00 00 F2
Send to Starline: 0A 3F 82 82 FF 00 00 00 00 4C
Send to Starline: 0A EC 51 51 FF 00 00 00 00 97
выше нет ответов от сигналки, т.к. GSM ещё не привязан .
Начинаю на сигналке процедуру привязки GSM (7 раз нажал кн валет и включил
зажигание)
Starline Response: 0A 00 00 08 FF 00 00 00 00 11 CS is OK!
Door: 0 Ign: 1 Brake: 0 Trunk: 0 Hood: 0 Locks: 0 Ohrana: 0 Trevoga: 0 Shock: 0 Tilt: 0
Starline Response: 0B 58 61 00 00 00 00 00 00 C4 CS is OK!
Registration GSM successfully completed!
Starline Response: 0A 80 00 08 FF 00 00 00 00 91 CS is OK!
Door: 0 Ign: 1 Brake: 0 Trunk: 0 Hood: 0 Locks: 0 Ohrana: 0 Trevoga: 0 Shock: 0 Tilt: 0
т.к. GSM успешно привязан , выключаю зажигание
Starline Response: 0A 80 00 00 FF 00 00 00 00 89 CS is OK!
Door: 0 Ign: 0 Brake: 0 Trunk: 0 Hood: 0 Locks: 0 Ohrana: 0 Trevoga: 0 Shock: 0 Tilt: 0
Starline Response: 0A 00 00 00 FF 00 00 00 00 09 CS is OK!
Door: 0 Ign: 0 Brake: 0 Trunk: 0 Hood: 0 Locks: 0 Ohrana: 0 Trevoga: 0 Shock: 0 Tilt: 0
Ставлю на охрану с терминала
Send SMS Ohrana ON:
Send to Starline: 0A 9D D4 ED FF 00 00 00 00 67
Starline Response: 0A 60 00 00 FF 00 00 00 00 69 CS is OK!
Door: 0 Ign: 0 Brake: 0 Trunk: 0 Hood: 0 Locks: 1 Ohrana: 1 Trevoga: 0 Shock: 0 Tilt: 0
Снимаю с охраны с терминала
Send SMS Ohrana OFF:
Send to Starline: 0A EA A2 9B FF 00 00 00 00 30
Starline Response: 0A 00 00 00 FF 00 00 00 00 09 CS is OK!
Door: 0 Ign: 0 Brake: 0 Trunk: 0 Hood: 0 Locks: 0 Ohrana: 0 Trevoga: 0 Shock: 0 Tilt: 0
тут я включил зажигание
Starline Response: 0A 00 00 08 FF 00 00 00 00 11 CS is OK!
Door: 0 Ign: 1 Brake: 0 Trunk: 0 Hood: 0 Locks: 0 Ohrana: 0 Trevoga: 0 Shock: 0 Tilt: 0
Starline Response: 0A 80 00 08 FF 00 00 00 00 91 CS is OK!
Door: 0 Ign: 1 Brake: 0 Trunk: 0 Hood: 0 Locks: 0 Ohrana: 0 Trevoga: 0 Shock: 0 Tilt: 0
тут я выключил зажигание
Starline Response: 0A 80 00 00 FF 00 00 00 00 89 CS is OK!
Door: 0 Ign: 0 Brake: 0 Trunk: 0 Hood: 0 Locks: 0 Ohrana: 0 Trevoga: 0 Shock: 0 Tilt: 0
Starline Response: 0A 00 00 00 FF 00 00 00 00 09 CS is OK!
Door: 0 Ign: 0 Brake: 0 Trunk: 0 Hood: 0 Locks: 0 Ohrana: 0 Trevoga: 0 Shock: 0 Tilt: 0
Короче опять выдалось свободных пару часов. Написал скетч граббер. Не знаю, можно ли это сюда выкладывать, но этой херней можно снять с охраны систему, будучи стоящую на охране, по времемни не более чем за 10мин. а обычно 2…3мин.
Бывает установщикам такое нужно, когда блок сигналки валяется в хозяйстве , стоящий на охране , брелков от которого нет, а выкинуть жалко. А Угонщики, думаю, и без меня ужо всё придумали. Не думал, что можно довольно современную сигналку так легко хакнуть. Ну не легко конечно, имеется ввиду, в одно лицо и с таким небольшим скиллом как у меня.
Замки - они от честных людей…
Я правильно понимаю, что для взлома необходимо физически подцепиться к порту сигнализации?
Да, если это А91, А92, А94 и им подобные по году, у них есть синий 3пиновый разъем для подключения внешнего gsm модуля. Туда и надо подключаться. Для А93 внешних джсм модулей не было. Соответственно нужно снять корпус блока и подключиться к разъему. Предназначенному для. Gsm модуля который вставляется внутрь блока сигнализации.
Добавил определение состояния работы ДВС , кое что поправил. Адаптировал скетч, чтобы удобнее было вставлять в ваш проект. Позже может в библиотеку заверну.
#include <EEPROM.h>
#define SLDATA_RX 3 // пин ардуино (не менять!), выполняющий роль RX оригинального GSM - подключать к TX сигнализации
#define SLDATA_TX 2 // пин ардуино (не менять!), выполняющий роль TX оригинального GSM - подключать к RX сигнализации
#define SL_DEBUG // раскомментировать, если нужна отладка в терминал. (Закомментировать эту строку, когда вставляете эту городьбу в свой проект)
volatile byte SL_dataRX[10] = {0}; // буфер приема данных от сигналки
enum SL_statesRX {WAIT_FALL, WAITSTROB, CLOCKING_DETECTED}; // возможные состояния приемника
volatile byte SL_stateRX = WAIT_FALL ; // переменная состояния приемника
volatile byte SL_bitNumberRX = 0 ;
volatile byte SL_byteNumberRX = 0 ;
volatile bool SLmessage_received = 0; // флаг что принято новое сообщение от сигналки
volatile byte SL_dataTX[10]= {0}; // буфер передачи данных на сигналку (пакет байт команды)
enum SL_statesTX {WAIT_CLOCKING, PROPUSK, TXbyCLOCK, TXtoIDLE}; //возможные состояния передатчика
volatile byte SL_stateTX = WAIT_CLOCKING ; // переменная состояния передатчика
volatile byte SL_bitNumberTX = 0 ;
volatile byte SL_byteNumberTX = 0 ;
byte SL_key[2]={0}; // байты ключа сигнализации
// таймеры возврата в bus-Idle в случае неответов от сигналки
volatile bool Timer_waitCLOCKING_from_Starline = 0;
uint32_t prev_waitCLOCKING_from_Starline = 0;
enum protectTimer_states {TIMER_OFF, TIMER_WAIT_RESPONSE, TIMER_PROTECT, TIMER_LASTSTATE};
byte Timer_waitRESPONSE_from_Starline = 0;
uint32_t prev_waitRESPONSE_from_Starline = 0;
byte SL_Timer_needRepeat = 0;
uint32_t prev_SL_Timer_needRepeat = 0;
volatile bool SL_needPropusk = 1 ;
byte SL_RepeatCommand = 0 ;
byte SL_CountRepeat = 0 ;
#define CLOCK_ON TCCR2B=2
#define CLOCK_OFF TCCR2B=0
#define SEND_CLOCKING_AND_READ_BITS ISR(TIMER2_COMPA_vect)
const uint8_t SL_ZAPROS = 0x42;
const uint8_t SL_START_ENG = 0x21;
const uint8_t SL_STOP_ENG = 0x20;
const uint8_t SL_OHRANA_ON = 0x11;
const uint8_t SL_OHRANA_OFF = 0x10;
bool Doors = 0 ;
bool Locks = 0 ;
bool Ohrana = 0 ;
bool Trunk = 0 ;
bool Hood = 0 ;
bool Ignition = 0 ;
bool Brake = 0 ;
bool Engine = 0 ;
bool Trevoga = 0 ;
bool Tiltsensor = 0 ;
bool Shocksensor = 0 ;
void setup()
{
SL_Setup();
}
void loop()
{
SL_Data(); // работа протокола SL_DATA
}
void SL_Setup(){
pinMode (SLDATA_TX, OUTPUT); // линию TX на выход
digitalWrite (SLDATA_TX, 1); // и ставим в busIdle
pinMode (SLDATA_RX, INPUT_PULLUP); // линию RX на вход с подтяжкой
#ifdef SL_DEBUG
Serial.begin(115200); Serial.println(); Serial.println(F("Arduino Restart"));
Serial.print(F("Starline Key: "));
#endif
for (byte i=0; i<2; i++)
{
SL_key[i] = EEPROM.read(i+200);
#ifdef SL_DEBUG
if (SL_key[i]<0xF){Serial.print("0");} Serial.print(SL_key[i], HEX); Serial.print(F(" "));
#endif
}
#ifdef SL_DEBUG
Serial.println();
#endif
//---------настройка таймера2 для выполнения нами тактирования передачи от сигналки (обработчик выскочит раз в 100мкс).
TCCR2A = 2 ;
TCCR2B = 0;
OCR2A = 198; // установка регистра совпадения (100 мкс для прескалера 8)
TIMSK2 = 2; // разрешить прерывание по таймеру2 по сравнению A
//TCCR2B = 2; // включ таймер раз в 100мкс
}
void SL_Data()
{
//таймеры сброса тактирования или сброса линии TX при передаче в случае неответов от оппонента
timers_to_protect_against_failures();
#ifdef SL_DEBUG
//иницирование отправки команд на сигналку через терминал
Command_to_Starline_from_Terminal();
#endif
//обработка принятых сообщений от сигналки
processing_of_received_SLmessages();
//отправка сигнала тактирования на сигналку
send_CLOCKING_to_Starline();
}
void send_CLOCKING_to_Starline(){
if (Timer_waitRESPONSE_from_Starline!=TIMER_PROTECT){ // тактируем, если не включена защитная задержка глюков связи
bool curRX = digitalRead(SLDATA_RX);
static bool lastRX = curRX;
if (lastRX != curRX){ // если состояние линии RX изменилось
if (SL_stateTX==WAIT_CLOCKING && SL_stateRX == WAIT_FALL) // если статус приемника и передатчика "ждем спад"
{
if (lastRX && !curRX){ // если увидели спад на RX, значит сигналка хочет передавать, ниже отправляем ей тактирвание
SL_stateRX = WAITSTROB;
delayMicroseconds (100);
if (bool((1 << 3) & PIND)) {SL_stateRX = WAIT_FALL; return;} // если было ложное срабатывание RX пина, выходим.
//ниже включение таймера защиты от возможных глюков при неответах
if (Timer_waitRESPONSE_from_Starline==TIMER_OFF) {Timer_waitRESPONSE_from_Starline = TIMER_WAIT_RESPONSE; prev_waitRESPONSE_from_Starline = millis();}
digitalWrite (SLDATA_TX,0); // короткий строб в ноль, делаем всё по снифферской осциллограмме с ори обмена данными
delayMicroseconds (40); // длина строба
CLOCK_ON; // включаем тактирование для оппонента.
}
}
lastRX = curRX;
}
}
}
SEND_CLOCKING_AND_READ_BITS // обработчик вылазит раз в 100мкс, тактируем для сигналки и читаем очередной бит от неё
{
if (SL_stateRX == WAITSTROB) {SL_stateRX = CLOCKING_DETECTED; PORTD ^= (1 << 2);}
else if (SL_stateRX == CLOCKING_DETECTED)
{
if (bool((1 << 3) & PIND)){SL_dataRX[SL_byteNumberRX]|= (1<<(SL_bitNumberRX));}// читаем
else {SL_dataRX[SL_byteNumberRX]&=~(1<<(SL_bitNumberRX));} // очередной бит
PORTD ^= (1 << 2); // тактируем, изменив состояние пина TX на противоположное
if (SL_bitNumberRX==7 && SL_byteNumberRX == 9) {endRX(); SLmessage_received = 1; return;} // сообщение полностью принято
SL_bitNumberRX++; if (SL_bitNumberRX==8){SL_bitNumberRX=0; SL_byteNumberRX++;} // рост счётчиков бит и байт
}
}
void endRX(){CLOCK_OFF; SL_bitNumberRX=0; SL_byteNumberRX=0; SL_stateRX = WAIT_FALL;}
void processing_of_received_SLmessages()
{if (SLmessage_received){
#ifdef SL_DEBUG
Serial.print ("Starline Response: ");
#endif
byte CS = 0 ;
for (int i=0; i<10; i++)
{
if (i<9)CS+=SL_dataRX[i]; // подсчёт CS
#ifdef SL_DEBUG
if (SL_dataRX[i]<=0xF)Serial.print("0"); Serial.print(SL_dataRX[i], HEX); Serial.print(" ");
#endif
if (i==9)
{
#ifdef SL_DEBUG
Serial.print(" CS is ");
#endif
if (CS==SL_dataRX[i]) // если получен валидный ответ от сигналки
{
Timer_waitCLOCKING_from_Starline = 0; // сбрасываем таймер ожидания тактирования от сигналки
Timer_waitRESPONSE_from_Starline = TIMER_OFF; // сбрасываем таймер ожидания ответа от сигналки
SL_Timer_needRepeat = 0 ; SL_CountRepeat = 0 ;
#ifdef SL_DEBUG
Serial.println("OK! ");
#endif
if (SL_dataRX[0]==0x0B && SL_dataRX[4]==0x00) // принята процедура привязки GSM, запоминаем ключ Starline
{
Registration_SL_GSM();
#ifdef SL_DEBUG
Serial.println(F("Registration GSM successfully completed!"));
#endif
}
else {
Doors = (bool((1 << 0) & SL_dataRX[1]));
Trunk = (bool((1 << 2) & SL_dataRX[1]));
Hood = (bool((1 << 3) & SL_dataRX[1]));
Ignition = (bool((1 << 3) & SL_dataRX[3]));
Engine = (bool((1 << 3) & SL_dataRX[7]));
if ((bool((1 << 2) & SL_dataRX[3])) || (bool((1 << 2) & SL_dataRX[2])))Brake = 1; else Brake = 0;
Locks = (bool((1 << 5) & SL_dataRX[1]));
Ohrana = (bool((1 << 6) & SL_dataRX[1]));
Trevoga = (bool((1 << 4) & SL_dataRX[2]));
Shocksensor = (bool((1 << 1) & SL_dataRX[5]));
Tiltsensor = (bool((1 << 0) & SL_dataRX[6]));
// 7 бит третьего байта это тип КПП , 1-МКПП, 0-АКПП
#ifdef SL_DEBUG
Serial.print (" Door: "); Serial.print (Doors); Serial.print (" Ign: "); Serial.print (Ignition);
Serial.print (" Brake: "); Serial.print (Brake); Serial.print (" Trunk: "); Serial.print (Trunk);
Serial.print (" Hood: "); Serial.print (Hood); Serial.print (" Locks: "); Serial.print (Locks);
Serial.print (" Ohrana: "); Serial.print (Ohrana); Serial.print (" Engine: "); Serial.print (Engine);
Serial.print (" Trevoga: "); Serial.print (Trevoga);
Serial.print (" Shock: "); Serial.print (Shocksensor); Serial.print (" Tilt: "); Serial.println (Tiltsensor);
#endif
}
}
else // Если CS неправильная
{
#ifdef SL_DEBUG
Serial.println("Error!!!");
#endif
}
}
}
SLmessage_received = 0 ;
#ifdef SL_DEBUG
Serial.println();
#endif
}
}
#ifdef SL_DEBUG
void Command_to_Starline_from_Terminal() // инициирование отправки команд на сигналку с терминала
{
if (Serial.available())
{
Serial.println();
byte inbyte = Serial.read();
if (inbyte == 'z') {Serial.println (F(" Send SMS SL_ZAPROS Sostoyanya: ")); SL_sendcommand (SL_ZAPROS);}
else if (inbyte == '1') {Serial.println (F(" Send SMS Ohrana ON: ")); SL_sendcommand (SL_OHRANA_ON);}
else if (inbyte == '0') {Serial.println (F(" Send SMS Ohrana OFF: ")); SL_sendcommand (SL_OHRANA_OFF);}
else if (inbyte == 'r') {Serial.println (F(" GSM is reset! ")); Reset_SL_GSM(); }
else if (inbyte == 'p') {SL_needPropusk=!SL_needPropusk; Serial.print (F("Propusk ")); Serial.println (SL_needPropusk);}
}
}
#endif
void SL_sendcommand(const byte &SLcommand) // процедура отправки команды на сигналку
{
if (SL_stateRX > WAIT_FALL) {delay (200);}
SL_RepeatCommand = SLcommand;
SL_dataTX[0]=0x0A;
SL_dataTX[1]=millis();
SL_dataTX[2]=(SL_dataTX[1]^SLcommand)^SL_key[0];
SL_dataTX[3]=(SL_dataTX[1]^SLcommand)^SL_key[1];
SL_dataTX[4]=0xFF;
byte CS = 0 ;
for (byte i=0; i<5;i++) {CS+=SL_dataTX[i];}
SL_dataTX[9]=CS;
#ifdef SL_DEBUG
Serial.print (" Send to Starline: ");
for (byte i=0; i<10;i++) {if (SL_dataTX[i]<=0xF)Serial.print("0"); Serial.print(SL_dataTX[i], HEX); Serial.print(" ");}
Serial.println();
#endif
PORTD &=~(1 << 2); // садим в 0 линию передачи , инициируя желание передавать данные
//Timer_waitCLOCKING_from_Starline = 1; prev_waitCLOCKING_from_Starline = millis(); // включаем таймер защиты
SL_Timer_needRepeat = 1; prev_SL_Timer_needRepeat = millis();
attachInterrupt(1, Accept_clocking_and_transmit_bits, FALLING); // и ждем тактирования от сигналки (принимать тактирование будет внеш прерывание)
}
void Accept_clocking_and_transmit_bits () //обработчик внешнего прерывания, выступает как приёмник тактирования от сигналки для выполнения нашей ей передачки.
{
if (SL_stateTX==WAIT_CLOCKING){if (SL_needPropusk) SL_stateTX=PROPUSK; else SL_stateTX=TXbyCLOCK; attachInterrupt(1, Accept_clocking_and_transmit_bits, CHANGE);return;}
//--------------ниже передача команды на шину по тактированию от сигналки-----------
else if (SL_needPropusk && SL_stateTX==PROPUSK){SL_stateTX=TXbyCLOCK;}
else if (SL_stateTX==TXbyCLOCK) // принимаем тактирование от сигналки и по нему отправляем побитно команду
{
if (SL_bitNumberTX==0 && SL_byteNumberTX==0) {Timer_waitCLOCKING_from_Starline = 1; prev_waitCLOCKING_from_Starline = millis();} // включаем таймер защиты
if (bool((1 << (SL_bitNumberTX)) & SL_dataTX[SL_byteNumberTX])) { PORTD |=(1 << 2); } // читаем очередной бит из команды
else {PORTD &=~(1 << 2); } // и выставляем его на пине TX
//----------------------------------------------------------------------------------
if (SL_byteNumberTX==9 && SL_bitNumberTX == 7) { Timer_waitCLOCKING_from_Starline=0; endTX(); return;}// если все 80 бит переданы, выходим , сбросив переменные и откл внеш прерывание
SL_bitNumberTX++; if (SL_bitNumberTX == 8) {SL_bitNumberTX = 0 ;SL_byteNumberTX++;}
}
}
void endTX() {detachInterrupt(1); SL_stateTX=TXtoIDLE; SL_bitNumberTX=0; SL_byteNumberTX=0;}
void timers_to_protect_against_failures()
{
if (SL_stateTX==TXtoIDLE){delayMicroseconds(100); digitalWrite(SLDATA_TX,1);SL_stateTX=WAIT_CLOCKING;}
if (Timer_waitCLOCKING_from_Starline && millis()- prev_waitCLOCKING_from_Starline>=200)
{
Timer_waitCLOCKING_from_Starline=0;
endTX();
#ifdef SL_DEBUG
Serial.println (" CLOCKING from Starline is not end!!! ");
#endif
}
if (SL_Timer_needRepeat && millis() - prev_SL_Timer_needRepeat>=3500)
{
SL_CountRepeat++; if (SL_CountRepeat>=3) SL_CountRepeat = 3 ;
SL_Timer_needRepeat = 0 ;
SL_needPropusk=!SL_needPropusk;
if (SL_CountRepeat<3){SL_sendcommand (SL_RepeatCommand);}
}
if (Timer_waitRESPONSE_from_Starline>0 && millis() - prev_waitRESPONSE_from_Starline>=4000)
{
Timer_waitRESPONSE_from_Starline++;
if (Timer_waitRESPONSE_from_Starline==TIMER_PROTECT)
{
endRX();
digitalWrite(SLDATA_TX,1);
#ifdef SL_DEBUG
Serial.println (F("We are clocking , but we have not received a valid response from the Starline!!!"));
#endif
}
else if (Timer_waitRESPONSE_from_Starline>=TIMER_LASTSTATE){Timer_waitRESPONSE_from_Starline = TIMER_OFF;}
prev_waitRESPONSE_from_Starline = millis();
}
}
void Reset_SL_GSM () {SL_key[0]=0xFF; SL_key[1]=0xFF; EEPROM.write(200,0xFF);EEPROM.write(201,0xFF);}
void Registration_SL_GSM () {SL_key[0]=SL_dataRX[1]; SL_key[1]=SL_dataRX[2]; EEPROM.write(200,SL_dataRX[1]);EEPROM.write(201,SL_dataRX[2]);}
Продолжаю изучать протокол и свой монолог. Выше исследование, которые провел, были только в режиме GSM модуля по смс. То есть ори джсм не был зарегистрирован в приложении старлайн онлайн . Соответственно телематика 2.0 не работала. Попробовал заснифить обмен при зарегистрированном модуле в приложении , и вот оно, где температура ДВС передается, нашел наконец-то. В общем, когда телематические сообщения передаются, нулевой байт не 0x0A ,а принимает другие значения.
при подаче питания на сигу и GSM, последний шлет в сигналку такой кадр
01 00 00 00 00 00 00 00 00 01
сигналка отвечает тем же самым кадром.
далее GSM шлет на сигналку
02 00 00 00 00 00 00 00 00 02
при этом сига отвечает так:
02 46 49 32 35 2D 4F 35 00 A9
если нулевой байт (тип сообщения) и последний байт (CS) убрать, получаем ASCII сообщение от сигналки на джсм FI25-O5, это сига возвращает GSM модулю идент своей прошивки центрального блока.
и далее, если в приложении нажимать обновление данных, GSM на сигу шлет сначала привычным образом проверку состояния 42 (кадр там с нулевым байтом 0A)
0A 95 8F B6 FF 00 00 00 00 E3
и сразу за ним запрос состояния по протоколу телематики
70 00 00 00 FF 00 00 00 00 6F
сигналка на запрос состояния по телематике отвечает так:
70 5A A0 00 00 00 00 19 2C AF
короче нулевой байт 70h это телематическое сообщение, в котором GSM опрашивает дополнительные параметры сигналки, которые не были сделаны в протоколе до появления телематики. Кстати инфу о напряжении АКБ GSM берёт не от сигналки , а сам его мереет своими силами. Поэтому инфы о напряжении в сообщении телематики нет.
Разберем выше ответ телематики от сигналки . 0x5A 0xA0 я пока не разобрался, что это такое . А вот два последние байта перед CS это температуры , пока формулы такие. tсалона = левый байт, tдвс = правый байт . В данном случае t салона: +25 градусов , двс: +44 градуса.
Дырявость старлайна вроде давно не секрет… или я с Шерханом путаю?
да путаешь. Старлайн норм сигналки…как мне казалось до этого времени))) Шерхан вообще просто гавнище. Конечно я не ожидал, что можно вот так с охраны снять. В новом поколении, думаю, усложнили. Я на последних А93 v2 не пробовал, но раз GSM модуль подходит такой же, протокол должен быть одинаковый.
ну и, как выяснилось, всё таки на А93 v1 была возможность установки внешнего GSM , синий трёх пиновый разъем для GSM там присутствовал, что чуть убыстряет подключение (не надо разбирать блок). На A93 v2 разъем GSM убрали .
В любом случае, при угоне вору придётся вскрыть тачку , найти блок подлючиться , ну уже тогда пиши пропала. Обычно , я думаю, происходит все проще. На всех А93 v2 и всех моделях до нее , есть пин код для снятие с охраны без брелока, Дак вои заводской имеет значение 3 . При установке сигнализации думаю очень малый процент установщиков меняют пин (можно сделать до 3х значного). Поэтому угоняют, скорее всего просто вводом пина. Так что запрограммируйте пин код, если у вас A93 v2 и ниже. На последующих моделях это исправили и идёт карточка с уникальным пином в каждой коробке сиги свой пин.
все эти сигналки такая шняга, что я за 30 лет автостажа НИ НА ОДНУ СВОЮ МАШИНУ ничего дополнительно не ставил. Что было с завода - на том и езжу.
А вот снимать уже установленные - приходилось
Как-то в Хорватии на отдыхе уронил ключи в море
Брелок сдох. Пришлось искать местных ребят, которые за 15 минут тупо кусачками удалили у меня всю сигнализацию
Так потом и издил года два вообще без сигналки, пока не продал.
Пишу совершенно не боясь, что меня теперь вычислят и угонят машину ![]()
90 процентов людей ставят их для комфорта, а не от угона. Автозапуск прежде всего
ага, а потом мы смотрим видео как пустая машина нарезает круги ![]()
да не, такого уже давно нет. Ну от установщика конечно зависит, с дуру то можно и х… сломать . Щас сиги хорошие пошли, научились делать. Я старлайнов прикрутил более 200 , может даже ещё больше. Только положительные эмоции. А вот пандора нервы потрепала очень сильно, щас может конечно они реабилитировались, очень давно их не прикручивал. Про шерханы и прочую шляпу я молчу, категорически нельзя их ставить.
70 5A A0 00 00 00 00 19 2C AF
уже разобрался . 5A - левый полубайт это чувствительность тревожного уровня датчика удара, правый полубайт - чувствительность предупредительного уровня датчика удара
A0 - левый полубайт чувствительность датчика наклона .
где 0x0 - минимальная чувствительность , 0xE -максимальная
правый полубайт это время работы двс при дист и автозапуске
0 - это 10мин,
1 - 20мин,
2 - 30мин,
3 - постоянно (пока не заглушить).
время работы двс , я так понял, задается командой-кадром с нулевым байтом 0x70 и четвертым со значением не FF, например, установить время работы запуска 20 мин будет так:
70 00 01 00 00 00 00 00 00 71
(заметьте 4й байт при этом не FF, если бы был FF, это просто запрос состояния)
Чтобы установить новые значения датчиков удара и/или наклона, отправляем на сигналку такой кадр
71 24 F0 00 00 00 00 00 00 85
где 24 и F0 новые настройки для датчиков. Значит нулевой байт 0x71 это тип сообщения - настройка датчиков удара, наклона .
Ответ от сигналки ожидаемый:
70 24 F0 00 00 00 00 19 2C C9
идем дальше.
такая команда на сигналку - это задать автозапуск по температуре
70 00 00 00 00 00 03 00 00 73
где жирный байт это температура (отрицательная. В данном случае -3), при которой произойдет автозапуск. диапазон от 3 до 27 (в хексе от 0x03 до 0x1B) с шагом 3.
такая команда на сигналку - это задать автозапуск по интервалам времени
70 00 00 02 00 00 00 00 00 72
где жирный байт это интервал часов, через который будет происходить автозапуск. диапазон от 2 до 24(в хексе от 0x02 до 0x18) с шагом 2.
такая команда на сигналку - это задать автозапуск по будильнику
70 00 00 00 60 84 00 00 00 54
но пока не разобрался как эти байты несут смысловую нагрузку.
в ответе состояния от сигналки все эти параметры будут находится в тех же байтах. Таким образом, разобрали большинство телематических команд от GSM на сигналку и все байты телематического ответа состояния сигналки (с нулевым байтом 0x70), что за что отвечает.