//OpenSCADA module DAQ.FT3 file: BTR.cpp /*************************************************************************** * Copyright (C) 2011-2016 by Maxim Kochetkov * * fido_max@inbox.ru * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; version 2 of the License. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include "mod_FT3.h" #include "BTR.h" using namespace FT3; KA_BTU::KA_BTU(TMdPrm& prm, uint16_t id, uint16_t nu, bool has_params) : DA(prm), ID(id), count_nu(nu), with_params(has_params), config(4 | (nu << 4) | (16 << 10)) { mTypeFT3 = KA; TFld * fld; mPrm.p_el.fldAdd(fld = new TFld("state", _("State"), TFld::Integer, TFld::NoWrite)); fld->setReserve("0:0"); if(mPrm.owner().cfg("PRTTYPE").getS() == "KA") { mPrm.p_el.fldAdd(fld = new TFld("execution", _("Execution"), TFld::Integer, TVal::DirWrite)); fld->setReserve("0:2"); } for(int i = 0; i < count_nu; i++) { AddChannel(i); } loadIO(true); } KA_BTU::~KA_BTU() { TUdata.clear(); } void KA_BTU::AddChannel(uint8_t iid) { TUdata.push_back(SKATUchannel(iid, this)); AddAttr(TUdata.back().Line.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:0", iid + 1)); if(with_params) { for(int i = 0; i < 16; i++) { AddAttr(TUdata.back().Time[i].lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:%d", iid + 1, i + 1)); } } } string KA_BTU::getStatus(void) { string rez; if(NeedInit) { rez = "20: Опрос"; } else { rez = "0: Норма"; } return rez; } uint16_t KA_BTU::GetState() { tagMsg Msg; uint16_t rc = BlckStateUnknown; Msg.L = 5; Msg.C = AddrReq; *((uint16_t *) Msg.D) = PackID(ID, 0, 0); //state if(mPrm.owner().DoCmd(&Msg) == GOOD3) { switch(mPrm.vlAt("state").at().getI(0, true)) { case KA_BTU_Error: rc = BlckStateError; break; case KA_BTU_Normal: rc = BlckStateNormal; break; } } return rc; } uint16_t KA_BTU::SetParams(void) { uint16_t rc; tagMsg Msg; loadParam(); for(int i = 0; i < count_nu; i++) { Msg.L = 0; Msg.C = SetData; for(int j = 0; j < 16; j++) { Msg.L += SerializeUi16(Msg.D + Msg.L, PackID(ID, i + 1, j + 1)); Msg.L += SerializeUi16(Msg.D + Msg.L, TUdata[i].Time[j].lnk.vlattr.at().getI(0, true)); } Msg.L += 3; rc = mPrm.owner().DoCmd(&Msg); if((rc == BAD2) || (rc == BAD3)) { mPrm.mess_sys(TMess::Error, "Can't set channel %d", i + 1); } else { if(rc == ERROR) { mPrm.mess_sys(TMess::Error, "No answer to set channel %d", i + 1); break; } } } return rc; } uint16_t KA_BTU::RefreshData(void) { tagMsg Msg; Msg.L = 0; Msg.C = AddrReq; for(int i = 1; i <= count_nu; i++) { Msg.L += SerializeUi16(Msg.D + Msg.L, PackID(ID, i, 0)); } Msg.L += 3; return mPrm.owner().DoCmd(&Msg); } uint16_t KA_BTU::RefreshParams(void) { uint16_t rc; tagMsg Msg; for(int i = 1; i <= count_nu; i++) { Msg.L = 0; Msg.C = AddrReq; for(int j = 1; j <= 16; j++) { Msg.L += SerializeUi16(Msg.D + Msg.L, PackID(ID, i, j)); } Msg.L += 3; rc = mPrm.owner().DoCmd(&Msg); if((rc == BAD2) || (rc == BAD3)) { mPrm.mess_sys(TMess::Error, "Can't refresh channel %d params", i); } else { if(rc == ERROR) { mPrm.mess_sys(TMess::Error, "No answer to refresh channel %d params", i); break; } } } return rc; } void KA_BTU::loadIO(bool force) { if(mPrm.owner().startStat() && !force) { mPrm.modif(true); return; } //Load/reload IO context only allow for stopped controllers for prevent throws for(int i = 0; i < count_nu; i++) { loadLnk(TUdata[i].Line.lnk); for(int j = 0; j < 16; j++) { loadLnk(TUdata[i].Time[j].lnk); } } } void KA_BTU::saveIO() { //Save links for(int i = 0; i < count_nu; i++) { saveLnk(TUdata[i].Line.lnk); for(int j = 0; j < 16; j++) { saveLnk(TUdata[i].Time[j].lnk); } } } void KA_BTU::saveParam(void) { for(int i = 0; i < count_nu; i++) { saveVal(TUdata[i].Line.lnk); for(int j = 0; j < 16; j++) { saveVal(TUdata[i].Time[j].lnk); } } } void KA_BTU::loadParam(void) { if(mess_lev() == TMess::Debug) mPrm.mess_sys(TMess::Debug, "load param"); for(int i = 0; i < count_nu; i++) { loadVal(TUdata[i].Line.lnk); for(int j = 0; j < 16; j++) { loadVal(TUdata[i].Time[j].lnk); } } } void KA_BTU::tmHandler(void) { for(int i = 0; i < count_nu; i++) { for(int j = 0; j < 16; j++) { UpdateParamW(TUdata[i].Time[j], PackID(ID, i + 1, j + 1), 1); } } NeedInit = false; } uint16_t KA_BTU::HandleEvent(int64_t tm, uint8_t * D) { FT3ID ft3ID = UnpackID(TSYS::getUnalign16(D)); if(ft3ID.g != ID) return 0; uint16_t l = 0; if(ft3ID.k == 0) { switch(ft3ID.n) { case 0: mPrm.vlAt("state").at().setI(D[2], tm, true); l = 3; break; case 1: l = 4; break; case 2: mPrm.vlAt(TSYS::strMess("execution")).at().setI(D[3], tm, true); l = 4; break; } } else { if(count_nu && (ft3ID.k <= count_nu)) { switch(ft3ID.n) { case 0: mPrm.vlAt(TSYS::strMess("Line_%d", ft3ID.k)).at().setI(D[3], tm, true); l = 4; break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: if(with_params) { mPrm.vlAt(TSYS::strMess("Time%d_%d", ft3ID.n, ft3ID.k)).at().setI(TSYS::getUnalign16(D + 3), tm, true); } l = 5; break; case 32: if(with_params) { mPrm.vlAt(TSYS::strMess("line_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 3), tm, true); } l = 5; break; } } } return l; } uint8_t KA_BTU::cmdGet(uint16_t prmID, uint8_t * out) { FT3ID ft3ID = UnpackID(prmID); if(ft3ID.g != ID) return 0; uint l = 0; if(ft3ID.k == 0) { switch(ft3ID.n) { case 0: out[0] = 1; l = 1; break; case 1: out[0] = config & 0xFF; out[1] = (config >> 8) & 0xFF; l = 2; break; case 2: out[0] = 0; out[1] = 0; l = 2; break; } } else { if(count_nu && (ft3ID.k <= count_nu)) { switch(ft3ID.n) { case 0: out[0] = TUdata[ft3ID.k - 1].Line.s; out[1] = TUdata[ft3ID.k - 1].iTY; l = 2; break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: out[0] = TUdata[ft3ID.k - 1].Time[ft3ID.n - 1].s; out[1] = TUdata[ft3ID.k - 1].Time[ft3ID.n - 1].vl; out[2] = TUdata[ft3ID.k - 1].Time[ft3ID.n - 1].vl >> 8; l = 3; break; case 32: out[0] = TUdata[ft3ID.k - 1].Line.s; out[1] = TUdata[ft3ID.k - 1].Line.vl; out[1] = TUdata[ft3ID.k - 1].Line.vl >> 8; l = 3; break; } } } return l; } uint8_t KA_BTU::runTU(uint8_t tu) { uint8_t rc = 0; if(tu == 0x55) { for(int i = 0; i < count_nu; i++) { if(TUdata[i].iTY) { if(TUdata[i].Line.lnk.Connected()) { TUdata[i].Line.lnk.aprm.at().setI(TUdata[i].Line.vl); TUdata[i].Line.vl = 0; TUdata[i].iTY = 0; rc = 3; } } } } if(tu == 0x0) { for(int i = 0; i < count_nu; i++) { if(TUdata[i].Line.lnk.Connected()) { TUdata[i].Line.vl = 0; TUdata[i].iTY = 0; TUdata[i].Line.lnk.aprm.at().setI(TUdata[i].Line.vl); rc = 3; } } } return rc; } uint8_t KA_BTU::cmdSet(uint8_t * req, uint8_t addr) { uint16_t prmID = TSYS::getUnalign16(req); FT3ID ft3ID = UnpackID(prmID); if(ft3ID.g != ID) return 0; uint l = 0; uint8_t E[2]; // if(mess_lev() == TMess::Debug) mPrm.mess_sys(TMess::Debug, "cmdSet k %d n %d", ft3ID.k, ft3ID.n); if(ft3ID.k == 0) { switch(ft3ID.n) { case 2: l = runTU(req[2]); if(l) { uint8_t E[2] = { addr, req[2] }; PushInBE(1, sizeof(E), prmID, E); } break; } } else { if(count_nu && (ft3ID.k <= count_nu)) { switch(ft3ID.n) { case 0: TUdata[ft3ID.k - 1].Line.s = addr; TUdata[ft3ID.k - 1].iTY = req[2]; TUdata[ft3ID.k - 1].Line.vl = 1 << TUdata[ft3ID.k - 1].iTY - 1; l = 3; E[0] = addr; E[1] = req[2]; PushInBE(1, sizeof(E), prmID, E); break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: l = SetNewWVal(TUdata[ft3ID.k - 1].Time[ft3ID.n - 1], addr, prmID, TSYS::getUnalign16(req + 2)); break; case 32: TUdata[ft3ID.k - 1].Line.s = addr; TUdata[ft3ID.k - 1].iTY = 1; TUdata[ft3ID.k - 1].Line.vl = TSYS::getUnalign16(req + 2); l = 3; E[0] = addr; E[1] = req[2]; PushInBE(1, sizeof(E), prmID, E); break; } } } return l; } uint16_t KA_BTU::setVal(TVal &val) { uint16_t rc = 0; int off = 0; FT3ID ft3ID; ft3ID.k = s2i(TSYS::strParse(val.fld().reserve(), 0, ":", &off)); ft3ID.n = s2i(TSYS::strParse(val.fld().reserve(), 0, ":", &off)); ft3ID.g = ID; tagMsg Msg; uint8_t run; Msg.L = 0; Msg.C = SetData; Msg.L += SerializeUi16(Msg.D + Msg.L, PackID(ft3ID)); if(ft3ID.k == 0) { switch(ft3ID.n) { case 2: run = val.getI(0, true); if(run == 170) { Msg.L += SerializeB(Msg.D + Msg.L, 0); } else { if(run == 85) { Msg.L += SerializeB(Msg.D + Msg.L, run); } else { Msg.L = 0; } } break; } } else { if(count_nu && (ft3ID.k <= count_nu)) { rc = 1; if(ft3ID.n == 0) { Msg.L += SerializeB(Msg.D + Msg.L, val.getI(0, true)); } else { if(ft3ID.n <= 16) { Msg.L += SerializeUi16(Msg.D + Msg.L, val.getI(0, true)); } else { Msg.L = 0; rc = 0; } } } } if(Msg.L > 2) { Msg.L += 3; mPrm.owner().DoCmd(&Msg); } return rc; } B_BTR::B_BTR(TMdPrm& prm, uint16_t id, uint16_t nu, uint16_t nr, bool has_params) : DA(prm), ID(id), count_nu(nu), count_nr(nr), with_params(has_params) { mTypeFT3 = GRS; TFld * fld; if(count_nr) { blkID = 70; } else { blkID = 30; } mPrm.p_el.fldAdd(fld = new TFld("state", _("State"), TFld::Integer, TFld::NoWrite)); fld->setReserve("0:0"); if(count_nu) { mPrm.p_el.fldAdd(fld = new TFld("selection", _("Select TU"), TFld::Integer, TVal::DirWrite)); fld->setReserve("0:1"); mPrm.p_el.fldAdd(fld = new TFld("execution", _("Execution"), TFld::Integer, TVal::DirWrite)); fld->setReserve("0:2"); } for(int i = 0; i < count_nu; i++) { AddTUChannel(i); } for(int i = 0; i < count_nr; i++) { AddTRChannel(i); } loadIO(true); } B_BTR::~B_BTR() { } void B_BTR::AddTUChannel(uint8_t iid) { TUdata.push_back(STUchannel(iid, this)); AddAttr(TUdata.back().On.lnk, TFld::Boolean, TVal::DirWrite, "0:1"); AddAttr(TUdata.back().Off.lnk, TFld::Boolean, TVal::DirWrite, "0:1"); AddAttr(TUdata.back().Run.lnk, TFld::Boolean, TVal::DirWrite, "0:2"); AddAttr(TUdata.back().Reset.lnk, TFld::Boolean, TVal::DirWrite, "0:2"); if(with_params) { AddAttr(TUdata.back().Time.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:0", iid + 1)); AddAttr(TUdata.back().TC.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:1", iid + 1)); AddAttr(TUdata.back().ExTime.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:2", iid + 1)); } } void B_BTR::AddTRChannel(uint8_t iid) { TRdata.push_back(STRchannel(iid, this)); AddAttr(TRdata.back().Value.lnk, TFld::Real, TVal::DirWrite, TSYS::strMess("%d:0", iid + 1 + count_nu)); } string B_BTR::getStatus(void) { string rez; if(NeedInit) { rez = "20: Опрос"; } else { rez = "0: Норма"; } return rez; } void B_BTR::loadIO(bool force) { if(mPrm.owner().startStat() && !force) { mPrm.modif(true); return; } //Load/reload IO context only allow for stopped controllers for prevent throws for(int i = 0; i < count_nu; i++) { loadLnk(TUdata[i].On.lnk); loadLnk(TUdata[i].Off.lnk); loadLnk(TUdata[i].Run.lnk); loadLnk(TUdata[i].Reset.lnk); loadLnk(TUdata[i].Time.lnk); loadLnk(TUdata[i].TC.lnk); loadLnk(TUdata[i].ExTime.lnk); } for(int i = 0; i < count_nr; i++) { loadLnk(TRdata[i].Value.lnk); } } void B_BTR::saveIO() { //Save links for(int i = 0; i < count_nu; i++) { saveLnk(TUdata[i].On.lnk); saveLnk(TUdata[i].Off.lnk); saveLnk(TUdata[i].Run.lnk); saveLnk(TUdata[i].Reset.lnk); saveLnk(TUdata[i].Time.lnk); saveLnk(TUdata[i].TC.lnk); saveLnk(TUdata[i].ExTime.lnk); } for(int i = 0; i < count_nr; i++) { saveLnk(TRdata[i].Value.lnk); } } void B_BTR::tmHandler(void) { NeedInit = false; for(int i = 0; i < count_nu; i++) { UpdateParamW(TUdata[i].Time, PackID(ID, i + 1, 0), 1); UpdateParamW(TUdata[i].TC, PackID(ID, i + 1, 1), 1); UpdateParam8(TUdata[i].ExTime, PackID(ID, i + 1, 2), 1); } for(int i = 0; i < count_nr; i++) { UpdateParamFl(TRdata[i].Value, PackID(ID, i + 1 + count_nu, 0), 1); } } uint16_t B_BTR::Task(uint16_t uc) { tagMsg Msg; uint16_t rc = 0; switch(uc) { case TaskRefresh: Msg.L = 5; Msg.C = AddrReq; *((uint16_t *) Msg.D) = PackID(ID, 0, 0); //состояние if(mPrm.owner().DoCmd(&Msg)) { if(Msg.C == GOOD3) { if(count_nu) { Msg.L = 7; Msg.C = AddrReq; *((uint16_t *) (Msg.D)) = PackID(ID, 0, 1); //выбор ТУ *((uint16_t *) (Msg.D + 2)) = PackID(ID, 0, 2); //исполнение mPrm.owner().DoCmd(&Msg); if(with_params) { for(int i = 1; i <= count_nu; i++) { Msg.L = 9; *((uint16_t *) Msg.D) = PackID(ID, i, 0); //время выдержки *((uint16_t *) (Msg.D + 2)) = PackID(ID, i, 1); //ТС *((uint16_t *) (Msg.D + 4)) = PackID(ID, i, 2); //доп время выдержки if(mPrm.owner().DoCmd(&Msg)) { if(Msg.C == GOOD3) { rc = 1; } else { rc = 0; break; } } else { rc = 0; break; } } } } if(count_nr) { for(int i = 1; i <= count_nr; i++) { Msg.L = 5; Msg.C = AddrReq; *((uint16_t *) Msg.D) = PackID(ID, i + count_nu, 0); //уставка if(mPrm.owner().DoCmd(&Msg)) { if(Msg.C == GOOD3) { rc = 1; } else { rc = 0; break; } } else { rc = 0; break; } } } else { rc = 1; } } } if(rc) NeedInit = false; break; } return rc; } uint16_t B_BTR::HandleEvent(int64_t tm, uint8_t * D) { FT3ID ft3ID = UnpackID(TSYS::getUnalign16(D)); if(ft3ID.g != ID) return 0; uint16_t l = 0; if(ft3ID.k == 0) { switch(ft3ID.n) { case 0: mPrm.vlAt("state").at().setI(D[2], tm, true); l = 3; break; case 1: mPrm.vlAt(TSYS::strMess("selection")).at().setI(D[3], tm, true); l = 4; break; case 2: mPrm.vlAt(TSYS::strMess("execution")).at().setI(D[3], tm, true); l = 4; break; } } if(count_nu && (ft3ID.k <= count_nu)) { switch(ft3ID.n) { case 0: mPrm.vlAt(TSYS::strMess("time_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 3), tm, true); l = 5; break; case 1: if(with_params) { mPrm.vlAt(TSYS::strMess("tc_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 3), tm, true); } l = 5; break; case 2: if(with_params) { mPrm.vlAt(TSYS::strMess("extime_%d", ft3ID.k)).at().setI(D[3], tm, true); ; } l = 4; break; } } if(count_nr && ((ft3ID.k > count_nu) && (ft3ID.k <= count_nr + count_nu))) { switch(ft3ID.n) { case 0: mPrm.vlAt(TSYS::strMess("value_%d", ft3ID.k - count_nu)).at().setR(TSYS::getUnalignFloat(D + 3), tm, true); l = 7; break; } } return l; } uint8_t B_BTR::cmdGet(uint16_t prmID, uint8_t * out) { FT3ID ft3ID = UnpackID(prmID); if(ft3ID.g != ID) return 0; uint l = 0; if(ft3ID.k == 0) { switch(ft3ID.n) { case 0: out[0] = 0 | blkID; l = 1; break; case 1: out[0] = 0; out[1] = 0; l = 2; break; case 2: out[0] = 0; out[1] = 0; l = 2; break; } } else { if(count_nu && (ft3ID.k <= count_nu)) { switch(ft3ID.n) { case 0: out[0] = TUdata[ft3ID.k - 1].Time.s; out[1] = TUdata[ft3ID.k - 1].Time.vl; out[2] = TUdata[ft3ID.k - 1].Time.vl >> 8; l = 3; break; case 1: out[0] = TUdata[ft3ID.k - 1].TC.s; out[1] = TUdata[ft3ID.k - 1].TC.vl; out[2] = TUdata[ft3ID.k - 1].TC.vl >> 8; l = 3; break; case 2: out[0] = TUdata[ft3ID.k - 1].ExTime.s; out[1] = TUdata[ft3ID.k - 1].ExTime.vl; l = 2; break; } } if(count_nr && ((ft3ID.k > count_nu) && (ft3ID.k <= count_nr + count_nu))) { out[0] = TRdata[ft3ID.k - 1 - count_nu].Value.s; for(uint8_t j = 0; j < 4; j++) out[1 + j] = TRdata[ft3ID.k - 1 - count_nu].Value.b_vl[j]; l = 5; } } return l; } uint8_t B_BTR::cmdSet(uint8_t * req, uint8_t addr) { uint16_t prmID = TSYS::getUnalign16(req); FT3ID ft3ID = UnpackID(prmID); if(ft3ID.g != ID) return 0; uint l = 0; // if(mess_lev() == TMess::Debug) mPrm.mess_sys(TMess::Debug, "cmdSet k %d n %d", ft3ID.k, ft3ID.n); if(ft3ID.k == 0) { switch(ft3ID.n) { case 1: setTU(req[2]); l = 3; break; case 2: runTU(req[2]); l = 3; break; } } else { if(count_nu && (ft3ID.k <= count_nu)) { switch(ft3ID.n) { case 0: l = SetNewWVal(TUdata[ft3ID.k - 1].Time, addr, prmID, TSYS::getUnalign16(req + 2)); break; case 1: l = SetNewWVal(TUdata[ft3ID.k - 1].TC, addr, prmID, TSYS::getUnalign16(req + 2)); break; case 2: l = SetNew8Val(TUdata[ft3ID.k - 1].ExTime, addr, prmID, req[2]); break; } } if(count_nr && ((ft3ID.k > count_nu) && (ft3ID.k <= count_nr + count_nu))) { // if(mess_lev() == TMess::Debug) mPrm.mess_sys(TMess::Debug, "cmdSet Val"); l = SetNewflVal(TRdata[ft3ID.k - 1 - count_nu].Value, addr, prmID, TSYS::getUnalignFloat(req + 2)); } } return l; } void B_BTR::setTU(uint8_t tu) { uint8_t vl = tu >> 7; uint8_t n = tu & 0x7F; if((n > 0) && (n <= count_nu)) { STUchannel &TU = TUdata[n - 1]; currTU = n; if(vl) { if(TU.On.lnk.Connected()) { //on TU.On.lnk.aprm.at().setI(1); mPrm.vlAt(TU.On.lnk.prmName).at().setI(1, 0, true); } } else { if(TUdata[n - 1].Off.lnk.Connected()) { //off TU.Off.lnk.aprm.at().setI(1); mPrm.vlAt(TU.Off.lnk.prmName).at().setI(1, 0, true); } } } } void B_BTR::runTU(uint8_t tu) { if(currTU) { STUchannel &TU = TUdata[currTU - 1]; if((tu == 0x55) && (TU.Run.lnk.Connected())) { TU.Run.lnk.aprm.at().setI(1); mPrm.vlAt(TU.Run.lnk.prmName).at().setI(1, 0, true); currTU = 0; } } if(tu == 0x0) { for(int i = 0; i < count_nu; i++) { STUchannel & TU = TUdata[i]; if((TU.Reset.lnk.Connected())) { TU.Reset.lnk.aprm.at().setI(1); mPrm.vlAt(TU.Reset.lnk.prmName).at().setI(1, 0, true); } } currTU = 0; } } uint16_t B_BTR::setVal(TVal &val) { int off = 0; FT3ID ft3ID; ft3ID.k = s2i(TSYS::strParse(val.fld().reserve(), 0, ":", &off)); ft3ID.n = s2i(TSYS::strParse(val.fld().reserve(), 0, ":", &off)); ft3ID.g = ID; tagMsg Msg; Msg.L = 0; Msg.C = SetData; Msg.L += SerializeUi16(Msg.D + Msg.L, PackID(ft3ID)); uint8_t run; if(ft3ID.k == 0) { switch(ft3ID.n) { case 1: Msg.L += SerializeB(Msg.D + Msg.L, val.getI(0, true)); break; case 2: run = val.getI(0, true); if(run == 170) { Msg.L += SerializeB(Msg.D + Msg.L, 0); } else { if(run == 85) { Msg.L += SerializeB(Msg.D + Msg.L, run); } else { Msg.L = 0; } } break; } } else { if(count_nu && (ft3ID.k <= count_nu)) { switch(ft3ID.n) { case 0: Msg.L += SerializeUi16(Msg.D + Msg.L, val.getI(0, true)); break; case 1: Msg.L += SerializeUi16(Msg.D + Msg.L, val.getI(0, true)); break; case 2: Msg.L += SerializeB(Msg.D + Msg.L, val.getI(0, true)); break; } } if(count_nr && ((ft3ID.k > count_nu) && (ft3ID.k <= count_nr + count_nu))) { switch(ft3ID.n) { case 0: Msg.L += SerializeF(Msg.D + Msg.L, val.getR(0, true)); break; } } } if(Msg.L > 2) { Msg.L += 3; mPrm.owner().DoCmd(&Msg); } return 0; } //---------------------------------------------------------------------------