Ein Beispiel von miserablem Kode (String für einen AVR Arduino)
uint16_t NexText::getText(char *buffer, uint16_t len)
{
String cmd;
cmd += "get ";
cmd += getObjName();
cmd += ".txt";
sendCommand(cmd.c_str());
return recvRetString(buffer,len);
}
bool NexText::setText(const char *buffer)
{
String cmd;
cmd += getObjName();
cmd += ".txt=\"";
cmd += buffer;
cmd += "\"";
sendCommand(cmd.c_str());
return recvRetCommandFinished();
}
Keine Verwendung des F() Macros, keine Möglichkeit Feldnamen in PROGMEM zu legen.
Blockierende Kommunikation, Verwendung von goto ohne Not:
uint16_t recvRetString(char *buffer, uint16_t len, uint32_t timeout)
{
uint16_t ret = 0;
bool str_start_flag = false;
uint8_t cnt_0xff = 0;
String temp = String("");
uint8_t c = 0;
long start;
if (!buffer || len == 0)
{
goto __return;
}
start = millis();
while (millis() - start <= timeout)
{
while (nexSerial.available())
{
c = nexSerial.read();
if (str_start_flag)
{
if (0xFF == c)
{
cnt_0xff++;
if (cnt_0xff >= 3)
{
break;
}
}
else
{
temp += (char)c;
}
}
else if (NEX_RET_STRING_HEAD == c)
{
str_start_flag = true;
}
}
if (cnt_0xff >= 3)
{
break;
}
}
ret = temp.length();
ret = ret > len ? len : ret;
strncpy(buffer, temp.c_str(), ret);
__return:
dbSerialPrint("recvRetString[");
dbSerialPrint(temp.length());
dbSerialPrint(",");
dbSerialPrint(temp);
dbSerialPrintln("]");
return ret;
}
Delay() in der zentralen Kommunikation
void nexLoop(NexTouch *nex_listen_list[])
{
static uint8_t __buffer[10];
uint16_t i;
uint8_t c;
while (nexSerial.available() > 0)
{
delay(10);
c = nexSerial.read();
if (NEX_RET_EVENT_TOUCH_HEAD == c)
{
if (nexSerial.available() >= 6)
{
__buffer[0] = c;
for (i = 1; i < 7; i++)
{
__buffer[i] = nexSerial.read();
}
__buffer[i] = 0x00;
if (0xFF == __buffer[4] && 0xFF == __buffer[5] && 0xFF == __buffer[6])
{
NexTouch::iterate(nex_listen_list, __buffer[1], __buffer[2], (int32_t)__buffer[3]);
}
}
}
}
}
Verwendung von sprintf für eine triviale Formatierung
bool NexWaveform::addValue(uint8_t ch, uint8_t number)
{
char buf[15] = {0};
if (ch > 3)
{
return false;
}
sprintf(buf, "add %u,%u,%u", getObjCid(), ch, number);
sendCommand(buf);
return true;
}
Es ist nicht schwer es besser zu machen.
Ich habe damit mal angefangen, ich hänge es dir mal als Anhang an.
Die Dokumentation ist leider sehr rudimentär.
Ein Beispiel für diese Library
#include <WhandallSerial.h>
#include <WhandallNextion.h>
const unsigned int millisPerTick = 50;
const unsigned int ticksPerSecond = 1000 / millisPerTick;
void processCmd(const char* buf);
const char PROGMEM pmsEvt[] = "evt 0x";
const char PROGMEM pmsCntt[] = " cnt ";
// Main-0: datum-1, uhrzeit-2, wtag-4, msg1-8, msg2-9, msg3-14, btCat1-12, btCat2-13, (ticker-3, va0-5, va1-6, va2-7), nbGarden-10, nbNetw-11
// Garden-1: actGarden-3, nbMain-1, nbNetw-2
// Network-2: actAll-3, nbMain-1, nbGarden-2
const char pmsDatum[] PROGMEM = "datum";
const char pmsUhrzeit[] PROGMEM = "uhrzeit";
const char pmsWtag[] PROGMEM = "wtag";
const char pmsMsg1[] PROGMEM = "msg1";
const char pmsMsg2[] PROGMEM = "msg2";
const char pmsMsg3[] PROGMEM = "msg3";
const char pmsCat1[] PROGMEM = "btCat1";
const char pmsCat2[] PROGMEM = "btCat2";
const char pmsAGarden[] PROGMEM = "actGarden";
const char pmsAAll[] PROGMEM = "actAll";
const char pmsEquals[] PROGMEM = " = ";
const char pmsPage0[] PROGMEM = "page 0";
const char pmsBkcmd3[] PROGMEM = "bkcmd=3";
SSerial con(Serial, processCmd);
SSerial Nxi(NexSerial, NxObject::inHandler);
void pReasonT(nxReason reason, NxText* which) {
pReasonX(reason, (NxObject*)which);
}
void pReasonN(nxReason reason, NxNum* which) {
pReasonX(reason, (NxObject*)which);
}
void pReasonX(nxReason reason, NxObject* which) {
Serial.print(FPM(which->name()));
Serial.write(' ');
pNxReason(reason);
Serial.println();
}
void catAction(nxReason reason, NxNum* which) {
pReasonX(reason, which);
if (reason == up) {
which->get();
} else if (reason == retNum) {
Serial.print(FPM(which->name()));
Serial.print(FPM(pmsEquals));
Serial.println(which->accNumResult());
}
}
NxText nxDate(0, 1, pmsDatum, pReasonT);
NxText nxTime(0, 2, pmsUhrzeit, pReasonT);
NxText nxWtag(0, 4, pmsWtag, pReasonT);
NxText nxMsg1(0, 8, pmsMsg1, pReasonT);
NxText nxMsg2(0, 9, pmsMsg2, pReasonT);
NxText nxMsg3(0, 14, pmsMsg3, pReasonT);
NxNum nxCat1(0, 12, pmsCat1, catAction);
NxNum nxCat2(0, 13, pmsCat2, catAction);
NxText nxAGar(1, 3, pmsAGarden, pReasonT);
NxText nxAAll(2, 3, pmsAAll, pReasonT);
const char announce[] PROGMEM = "Mini Example";
void setup() {
Serial.begin(250000);
NexSerial.begin(115200);
con.begin(64);
Nxi.begin(64, optTripleFF | optKeepDlm);
NxObject::setGlobalHandler(pagePosHandler, commandHandler);
NxObject::prControl.fromEEProm();
Serial.println(AF(announce));
NexCommand_P(pmsBkcmd3);
NexCommand_P(pmsPage0);
}
void loop() {
con.loop();
Nxi.loop();
}
void withOneByte(const char* buf, void (*alAction)(uint8_t)) {
(*alAction)((uint8_t)strtol(++buf, NULL, 0));
}
void withAdrLenPrefix(const char* buf, void (*alAction)(const uint8_t*, int, const char*), const char* pfx = NULL) {
int len = 16;
char* satis;
uint8_t* res = (uint8_t*)strtol(++buf, &satis, 0);
if (*satis == ',' || *satis == ' ') {
len = (int)strtol(++satis, &satis, 0);
}
(*alAction)(res, len, pfx);
}
void withAdrLenPrefixLong(const char* buf, void (*alAction)(unsigned long, int, const char*), const char* pfx = NULL) {
int len;
char* satis;
unsigned long res = strtoul(++buf, &satis, 0);
if (*satis == ',' || *satis == ' ') {
len = (int)strtol(++satis, &satis, 0);
} else {
len = 16;
}
(*alAction)(res, len, pfx);
}
void processCmd(const char* buf) {
if (*buf == '!') {
if (*++buf) {
NexCommand(buf);
} else {
Serial.println(F("pass to Nextion"));
}
} else if (!NxObject::prControl.command('c', buf)) {
bool doClosingNewline = false;
switch (*buf) {
case 'v':
Serial.println(AF(announce));
break;
default:
Serial.print(F("Unknown CMD '"));
Serial.print(buf);
Serial.println(F("'"));
Serial.print(F("try v or !"));
doClosingNewline = true;
}
if (doClosingNewline) {
Serial.println();
}
}
}
void pagePosHandler(nxReason reason, const void* hPtr) {
hPtr = hPtr;
switch (reason) {
case pageChange:
case pageRefresh:
break;
case unhandledId:
{
MsgTouch& tou = *(MsgTouch*)hPtr;
pNxReason(reason);
Serial.write(' ');
tou.print();
Serial.println();
}
break;
case transReady:
break;
case transDone:
break;
case down:
case up:
case done:
case error:
case retNum:
case retStr:
case downPos:
case upPos:
case downSleepPos:
case upSleepPos:
case sleep:
case wakeUp:
case reseted:
case launched:
case upgraded:
default:
break;
}
}
const char pmsUnex[] PROGMEM = "unexpected";
void commandHandler(nxReason reason, const void* hPtr) {
hPtr = hPtr;
pNxReason(reason);
switch (reason) {
case done:
break;
case error:
Serial.write(',');
Serial.write(' ');
NxObject::printCurrError();
break;
case retNum:
Serial.write(' ');
Serial.print(((MsgNumData*)hPtr)->value);
break;
case retStr:
Serial.write(' ');
((MsgStrData*)hPtr)->pText();
break;
default:
Serial.write(' ');
Serial.print(FPM(pmsUnex));
break;
}
Serial.println();
}
WhandallNextion.zip (1020 KB)