This commit is contained in:
Климов Андрей Николаевич
2023-04-10 19:19:45 +03:00
parent 927272824c
commit 30f7b36a9c
6 changed files with 255 additions and 97 deletions

Binary file not shown.

View File

@@ -0,0 +1,91 @@
@ECHO off
REM Wait X second for memory on Arduino Due is erased.
SET WAIT_ERASED=4
ECHO ------ External tool BossacArduinoDue started ------
REM number of command line arguments ok?
REM IF [%1]==[] GOTO error_args
REM IF [%2]==[] GOTO error_args
REM set command line arguments
SET BOSSACPATH=..\tools\win\tool-bossac\bossac.exe
SET BINFILE=firmware.bin
REM parse command line arguments
SET BOSSACPATH=%BOSSACPATH:"=%
SET BINFILE=%BINFILE:"=%
REM workeround for bug in Atmel Studio 6.0.1996 Service Pack 2
SET BINFILE=%BINFILE:\\=\%
SET BINFILE=%BINFILE:.cproj=%
REM bossac path exist?
IF NOT EXIST "%BOSSACPATH%" GOTO error_arg1
REM bin file exist?
IF NOT EXIST "%BINFILE%" GOTO error_binfile
REM fetch DeviceID of Arduino Due Programming Port from WMI Service
FOR /f "tokens=* skip=1" %%a IN ('wmic PATH Win32_SerialPort Where "Caption LIKE '%%BOSSA%%'" get DeviceID') DO (
SET COMX=%%a
GOTO exit1
)
REM Arduino Due Programming Port not exist
GOTO error_comport
:exit1
REM remove blank
SET COMPORT=%COMX: =%
REM report in Atmel Studio 6.0 IDE output window
ECHO BossacPath=%BOSSACPATH%
ECHO BinFile=%BINFILE%
ECHO Arduino Due Programming Port is detected as %COMPORT%.
REM The bossac bootloader only runs if the memory on Arduino Due is erased.
REM The Arduino IDE does this by opening and closing the COM port at 1200 baud.
REM This causes the Due to execute a soft erase command.
ECHO Forcing reset using 1200bps open/close on port
ECHO MODE %COMPORT%:1200,N,8,1
MODE %COMPORT%:1200,N,8,1
REM Wait X second for memory on Arduino Due is erased.
ECHO Wait for memory on Arduino Due is erased...
PING -n %WAIT_ERASED% 127.0.0.1>NUL
REM Execute bossac.exe
ECHO Execute bossac with command line:
"%BOSSACPATH%" -i --port=%COMPORT% --unlock -R
REM START /WAIT "" "%BOSSACPATH%" -i --port=%COMPORT% -u -e -w -v -b "%BINFILE%" -R
GOTO end
:error_args
ECHO Error: wrong number of command line arguments passed!
GOTO end
:error_arg1
ECHO Error: command line argument 1 - path to bossac.exe not exist! - "C:\Program Files (x86)\arduino-1.5.2\hardware\tools\bossac.exe"
ECHO Error: command line argument 1 - argument passed = %1
GOTO end
:error_arg2
ECHO Error: command line argument 2 - path to bin file not exist! - use $(OutputDirectory)\$(OutputFileName).bin
ECHO Error: command line argument 2 - argument passed = %1
GOTO end
:error_binfile
ECHO Error: bin file "%BINFILE%" not exist!
GOTO end
:error_comport
ECHO Error: Arduino Due Programming Port not found!
:end
ECHO ======================== Done ========================

View File

@@ -59,7 +59,7 @@ PING -n %WAIT_ERASED% 127.0.0.1>NUL
REM Execute bossac.exe
ECHO Execute bossac with command line:
"%BOSSACPATH%" -i --port=%COMPORT% -U false -e -u -w -v -b "%BINFILE%" -R
"%BOSSACPATH%" -i --port=%COMPORT% -U false -w -v -b "%BINFILE%" -R
REM START /WAIT "" "%BOSSACPATH%" -i --port=%COMPORT% -U false -e -w -v -b "%BINFILE%" -R
GOTO end

View File

@@ -60,7 +60,7 @@ PING -n %WAIT_ERASED% 127.0.0.1>NUL
REM Execute bossac.exe
ECHO Execute bossac with command line:
"%BOSSACPATH%" -i --port=%COMPORT% -u -e -w -v -b "%BINFILE%" -R
"%BOSSACPATH%" -i --port=%COMPORT% -w -v -b "%BINFILE%" -R
REM START /WAIT "" "%BOSSACPATH%" -i --port=%COMPORT% -u -e -w -v -b "%BINFILE%" -R
GOTO end

View File

@@ -19,21 +19,14 @@ extern bool disableCMD;
#define INTERVAL_AC_POLLING 5000L
//static int driverStatus = CST_UNKNOWN;
#define AC_FAILED 15
#define AC_UNKNOWN CST_UNKNOWN
#define AC_IDLE CST_INITIALIZED
#define AC_SENDING 2
static int fresh =0;
static int power = 0;
static int swing =0;
static int lock_rem =0;
static int cur_tmp = 0;
static int set_tmp = 0;
static int fan_spd = 0;
static int mode = 0;
long prevPolling = 0;
byte inCheck = 0;
byte qstn[] = {255,255,10,0,0,0,0,0,1,1,77,1,90}; // Команда опроса
byte data[37] = {}; //Массив данных
byte on[] = {255,255,10,0,0,0,0,0,1,1,77,2,91}; // Включение кондиционера
byte off[] = {255,255,10,0,0,0,0,0,1,1,77,3,92}; // Выключение кондиционера
byte lock[] = {255,255,10,0,0,0,0,0,1,3,0,0,14}; // Блокировка пульта
@@ -45,7 +38,10 @@ const char SWING_P[] PROGMEM = "swing";
const char RAW_P[] PROGMEM = "raw";
void out_AC::getConfig(){
ACSerial=&AC_Serial;
if (!item) return;
if (item->getArgCount())
switch(portNum=item->getArg(0)){
@@ -72,14 +68,24 @@ void out_AC::getConfig(){
void out_AC::InsertData(byte data[], size_t size){
int fresh =0;
int swing =0;
int lock_rem =0;
int cur_tmp = 0;
int set_tmp = 0;
int fan_spd = 0;
char s_mode[10];
set_tmp = data[B_SET_TMP]+16;
if (set_tmp>40 || set_tmp<16) return;
cur_tmp = data[B_CUR_TMP];
mode = data[B_MODE];
store->mode = data[B_MODE];
fan_spd = data[B_FAN_SPD];
swing = data[B_SWING];
power = data[B_POWER];
store->power = data[B_POWER];
lock_rem = data[B_LOCK_REM];
fresh = data[B_FRESH];
/////////////////////////////////
@@ -104,15 +110,15 @@ void out_AC::InsertData(byte data[], size_t size){
}
*/
debugSerial.print ("Power=");
debugSerial.println(power);
debugSerial.print ("AC: Power=");
debugSerial.println(store->power);
if (power & 0x08)
if (store->power & 0x08)
publishTopic(item->itemArr->name, "ON", "/quiet");
else publishTopic(item->itemArr->name, "OFF" , "/quiet");
if (power & 0x02) //Compressor on
if (store->power & 0x02) //Compressor on
publishTopic(item->itemArr->name, "ON","/compressor");
else
publishTopic(item->itemArr->name, "OFF","/compressor");
@@ -155,28 +161,28 @@ void out_AC::InsertData(byte data[], size_t size){
////////////////////////////////////
s_mode[0]='\0';
if (mode == 0x00){
if (store->mode == 0x00){
strcpy_P(s_mode,AUTO_P);
}
else if (mode == 0x01){
else if (store->mode == 0x01){
strcpy_P(s_mode,COOL_P);
}
else if (mode == 0x02){
else if (store->mode == 0x02){
strcpy_P(s_mode,HEAT_P);
}
else if (mode == 0x03){
else if (store->mode == 0x03){
strcpy_P(s_mode,FAN_ONLY_P);
}
else if (mode == 0x04){
else if (store->mode == 0x04){
strcpy_P(s_mode,DRY_P);
}
else if (mode == 109){
else if (store->mode == 109){
strcpy_P(s_mode,ERROR_P);
}
publishTopic(item->itemArr->name, (long) mode, "/mode");
publishTopic(item->itemArr->name, (long) store->mode, "/mode");
if (power & 0x01)
if (store->power & 0x01)
publishTopic(item->itemArr->name, s_mode,"/cmd");
else publishTopic(item->itemArr->name, "OFF","/cmd");
@@ -208,11 +214,17 @@ byte getCRC(byte req[], size_t size){
}
void out_AC::SendData(byte req[], size_t size){
if (!store || !item) return;
if (item->itemArr->subtype == AC_SENDING)
{
while (store->timestamp && !isTimeOver(store->timestamp,millis(),150)) yield();
}
ACSerial->write(req, size - 1);
ACSerial->write(getCRC(req, size-1));
//ACSerial->flush();
item->setExt(millisNZ());
debugSerial<<F("AirCon ")<<portNum<<F(" <<");
store->timestamp=millisNZ();
debugSerial<<F("AC: ")<<portNum<<F(" <<");
for (int i=0; i < size-1; i++)
{
if (req[i] < 10){
@@ -225,7 +237,7 @@ void out_AC::SendData(byte req[], size_t size){
}
}
debugSerial.println();
item->itemArr->subtype = AC_SENDING;
}
inline unsigned char toHex( char ch ){
@@ -238,19 +250,32 @@ int out_AC::Setup()
{
abstractOut::Setup();
if (!item) return 0;
debugSerial<<F("AC Init: ")<<portNum<<endl;
debugSerial<<F("AC: Init: ")<<portNum<<endl;
if (!store) store= (acPersistent *)item->setPersistent(new acPersistent);
if (!store)
{ errorSerial<<F("AC: Out of memory")<<endl;
return 0;}
memset(store->data,0,sizeof(acPersistent::data));
store->mode=0;
store->power=0;
store->inCheck=0;
store->timestamp=millisNZ();
if (!portNum)// && (g_APinDescription[0].ulPinType == PIO_PA8A_URXD))
{
pinMode(0, INPUT_PULLUP);
#if debugSerial == Serial
infoSerial<<F("Serial used by AC - disabling serial logging and cmd")<<
sysConf.setSerialDebuglevel(0);
infoSerial<<F("AC: Serial used by AC - disabling serial logging and cmd")<<endl;
//sysConf.setSerialDebuglevel(0);
serialDebugLevel = 0;
disableCMD=true;
#endif
}
ACSerial->begin(9600);
item->itemArr->subtype = CST_INITIALIZED;
item->itemArr->subtype = AC_IDLE;
//driverStatus = CST_INITIALIZED;
return 1;
}
@@ -258,7 +283,10 @@ return 1;
int out_AC::Stop()
{
if (!item) return 0;
debugSerial<<F("AC De-Init: ")<<portNum<<endl;
debugSerial<<F("AC: De-Init: ")<<portNum<<endl;
delete store;
item->setPersistent(NULL);
store = NULL;
item->itemArr->subtype = CST_UNKNOWN;
return 1;
}
@@ -266,49 +294,72 @@ return 1;
int out_AC::Status()
{
if (!item) return 0;
return item->itemArr->subtype;
switch (item->itemArr->subtype)
{
case AC_FAILED: return CST_FAILED;
case AC_UNKNOWN: return CST_UNKNOWN;
default:
return CST_INITIALIZED;
//return item->itemArr->subtype;
}
}
int out_AC::isActive()
{
return (power & 1);
if (!store) return 0;
return (store->power & 1);
}
int out_AC::Poll(short cause)
{
if (!store) return -1;
switch (item->itemArr->subtype)
{
case AC_FAILED: return -1;
case AC_UNKNOWN: return -1;
case AC_SENDING:
{
if (store->timestamp && isTimeOver(store->timestamp,millis(),150))
{
item->itemArr->subtype = AC_IDLE;
store->timestamp=millisNZ();
}
}
}
if (cause!=POLLING_SLOW) return false;
if (isTimeOver(prevPolling,millis(),INTERVAL_AC_POLLING)) {
prevPolling = millisNZ();
debugSerial.println(F("Polling"));
if ((item->itemArr->subtype == AC_IDLE) && isTimeOver(store->timestamp,millis(),INTERVAL_AC_POLLING))
{
debugSerial.println(F("AC: Polling"));
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
}
if(ACSerial->available() >= 37){ //was 0
ACSerial->readBytes(data, 37);
ACSerial->readBytes(store->data, 37);
while(ACSerial->available()){
delay(2);
ACSerial->read();
}
debugSerial<<F("AirCon ")<<portNum<<F(" >> ");
debugSerial<<F("AC: ")<<portNum<<F(" >> ");
for (int i=0; i < 37-1; i++)
{
if (data[i] < 10){
if (store->data[i] < 10){
debugSerial.print("0");
debugSerial.print(data[i], HEX);
debugSerial.print(store->data[i], HEX);
}
else
{
debugSerial.print(data[i], HEX);
debugSerial.print(store->data[i], HEX);
}
}
if (data[36] != inCheck){
inCheck = data[36];
InsertData(data, 37);
debugSerial<<F(" OK");
if (store->data[36] != store->inCheck){
store->inCheck = store->data[36];
InsertData(store->data, 37);
debugSerial<<F("AC: OK");
}
debugSerial.println();
@@ -335,14 +386,16 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
switch(suffixCode)
{
case S_SET:
set_tmp = cmd.getInt();
{
byte set_tmp = cmd.getInt();
if (set_tmp >= 16 && set_tmp <= 40)
{
//if (set_tmp>40 || set_tmp<16) set_temp=21;
data[B_SET_TMP] = set_tmp -16;
store->data[B_SET_TMP] = set_tmp -16;
publishTopic(item->itemArr->name,(long) set_tmp,"/set");
}
else return -1;
}
break;
case S_CMD:
@@ -351,52 +404,52 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
{
case CMD_ON:
case CMD_XON:
data[B_POWER] = power;
data[B_POWER] |= 1;
store->data[B_POWER] = store->power;
store->data[B_POWER] |= 1;
SendData(on, sizeof(on)/sizeof(byte));
// publishTopic(item->itemArr->name,"ON","/cmd");
return 1;
break;
case CMD_OFF:
case CMD_HALT:
data[B_POWER] = power;
data[B_POWER] &= ~1;
store->data[B_POWER] = store->power;
store->data[B_POWER] &= ~1;
SendData(off, sizeof(off)/sizeof(byte));
// publishTopic(item->itemArr->name,"OFF","/cmd");
return 1;
break;
case CMD_AUTO:
data[B_MODE] = 0;
data[B_POWER] = power;
data[B_POWER] |= 1;
store->data[B_MODE] = 0;
store->data[B_POWER] = store->power;
store->data[B_POWER] |= 1;
// strcpy_P(s_mode,AUTO_P);
break;
case CMD_COOL:
data[B_MODE] = 1;
data[B_POWER] = power;
data[B_POWER] |= 1;
store->data[B_MODE] = 1;
store->data[B_POWER] = store->power;
store->data[B_POWER] |= 1;
// strcpy_P(s_mode,COOL_P);
break;
case CMD_HEAT:
data[B_MODE] = 2;
data[B_POWER] = power;
data[B_POWER] |= 1;
store->data[B_MODE] = 2;
store->data[B_POWER] = store->power;
store->data[B_POWER] |= 1;
// strcpy_P(s_mode,HEAT_P);
break;
case CMD_DRY:
data[B_MODE] = 4;
data[B_POWER] = power;
data[B_POWER] |= 1;
store->data[B_MODE] = 4;
store->data[B_POWER] = store->power;
store->data[B_POWER] |= 1;
// strcpy_P(s_mode,DRY_P);
break;
case CMD_FAN:
data[B_MODE] = 3;
store->data[B_MODE] = 3;
// debugSerial<<"fan\n";
data[B_POWER] = power;
data[B_POWER] |= 1;
if (data[B_FAN_SPD] == 3)
store->data[B_POWER] = store->power;
store->data[B_POWER] |= 1;
if (store->data[B_FAN_SPD] == 3)
{
data[B_FAN_SPD] = 2; //Auto - fan speed in Ventilation mode not working
store->data[B_FAN_SPD] = 2; //Auto - fan speed in Ventilation mode not working
}
// strcpy_P(s_mode,FAN_ONLY_P);
break;
@@ -413,24 +466,24 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
switch (cmd.getCmd())
{
case CMD_AUTO:
data[B_FAN_SPD] = 3;
store->data[B_FAN_SPD] = 3;
strcpy_P(s_speed,AUTO_P);
break;
case CMD_HIGH:
data[B_FAN_SPD] = 0;
store->data[B_FAN_SPD] = 0;
strcpy_P(s_speed,HIGH_P);
break;
case CMD_MED:
data[B_FAN_SPD] = 1;
store->data[B_FAN_SPD] = 1;
strcpy_P(s_speed,MED_P);
break;
case CMD_LOW:
data[B_FAN_SPD] = 2;
store->data[B_FAN_SPD] = 2;
strcpy_P(s_speed,LOW_P);
break;
default:
//if (n) data[B_FAN_SPD] = Parameters[0];
data[B_FAN_SPD] = cmd.getInt();
store->data[B_FAN_SPD] = cmd.getInt();
//TODO - mapping digits to speed
}
publishTopic(item->itemArr->name,s_speed,"/fan");
@@ -438,17 +491,17 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
case S_MODE:
//data[B_MODE] = Parameters[0];
data[B_MODE] = cmd.getInt();
store->data[B_MODE] = cmd.getInt();
break;
case S_LOCK:
switch (cmd.getCmd())
{
case CMD_ON:
data[B_LOCK_REM] = 80;
store->data[B_LOCK_REM] = 80;
break;
case CMD_OFF:
data[B_LOCK_REM] = 0;
store->data[B_LOCK_REM] = 0;
break;
}
break;
@@ -457,16 +510,16 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
switch (cmd.getCmd())
{
case CMD_ON:
data[B_SWING] = 3;
store->data[B_SWING] = 3;
publishTopic(item->itemArr->name,"ON","/swing");
break;
case CMD_OFF:
data[B_SWING] = 0;
store->data[B_SWING] = 0;
publishTopic(item->itemArr->name,"OFF","/swing");
break;
default:
//if (n) data[B_SWING] = Parameters[0];
data[B_SWING] = cmd.getInt();
store->data[B_SWING] = cmd.getInt();
}
break;
@@ -475,10 +528,10 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
switch (cmd.getCmd())
{
case CMD_ON:
data[B_POWER] |= 8;
store->data[B_POWER] |= 8;
break;
case CMD_OFF:
data[B_POWER] &= ~8;
store->data[B_POWER] &= ~8;
break;
}
@@ -532,14 +585,16 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
//if (strTopic == "/myhome/in/Conditioner/RAW")
data[B_CMD] = 0;
data[9] = 1;
data[10] = 77;
data[11] = 95;
ACSerial->flush();
uint32_t ts=item->getExt();
while (ts && !isTimeOver(ts,millis(),100)) yield();
SendData(data, sizeof(data)/sizeof(byte));
store->data[B_CMD] = 0;
store->data[9] = 1;
store->data[10] = 77;
store->data[11] = 95;
///ACSerial->flush();
//uint32_t ts=item->getExt();
//while (ts && !isTimeOver(ts,millis(),100)) yield();
SendData(store->data, sizeof(store->data)/sizeof(byte));
//InsertData(data, sizeof(data)/sizeof(byte));
//ACSerial->flush();
//item->setExt(millisNZ());

View File

@@ -2,6 +2,7 @@
#pragma once
#ifndef AC_DISABLE
#include <abstractout.h>
#include <item.h>
#include "itemCmd.h"
#define LEN_B 37
@@ -21,10 +22,20 @@
//#define S_RAW S_ADDITIONAL+4
extern void modbusIdle(void) ;
class acPersistent : public chPersistent {
public:
byte data[37];
byte power;
byte mode;
byte inCheck;
uint32_t timestamp;
};
class out_AC : public abstractOut {
public:
out_AC(Item * _item):abstractOut(_item){getConfig();};
out_AC(Item * _item):abstractOut(_item){store = (acPersistent *) item->getPersistent(); getConfig();};
void getConfig();
int Setup() override;
int Poll(short cause) override;
@@ -36,6 +47,7 @@ public:
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true) override;
protected:
acPersistent * store;
void InsertData(byte data[], size_t size);
void SendData(byte req[], size_t size);
uint8_t portNum;