//OpenSCADA module DAQ.FT3 file: TANK.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 "TANK.h" using namespace FT3; void KA_TANK::SKATANKchannel::UpdateParam(uint16_t ID, uint8_t cl) { ui8w tmp[9]; tmp[0].w = TCSens1.Get(); tmp[1].w = TCSens1Not.Get(); tmp[2].w = TCSens2.Get(); tmp[3].w = TCSens2Not.Get(); tmp[4].w = TULight.Get(); tmp[5].w = TUSound.Get(); tmp[6].w = TURlOff.Get(); tmp[7].w = TimeDelay.Get(); tmp[8].w = TimeFalseAlarm.Get(); if(tmp[0].w != TCSens1.vl || tmp[1].w != TCSens1Not.vl || tmp[2].w != TCSens2.vl || tmp[3].w != TCSens2Not.vl || tmp[4].w != TULight.vl || tmp[5].w != TUSound.vl || tmp[6].w != TURlOff.vl || tmp[7].w != TimeDelay.vl || tmp[8].w != TimeFalseAlarm.vl) { TCSens1.s = 0; TCSens1.Update(tmp[0].w); TCSens1Not.Update(tmp[1].w); TCSens2.Update(tmp[2].w); TCSens2Not.Update(tmp[3].w); TULight.Update(tmp[4].w); TUSound.Update(tmp[5].w); TURlOff.Update(tmp[6].w); TimeDelay.Update(tmp[7].w); TimeFalseAlarm.Update(tmp[8].w); uint8_t E[19] = { 0, tmp[0].b[0], tmp[0].b[1], tmp[1].b[0], tmp[1].b[1], tmp[2].b[0], tmp[2].b[1], tmp[3].b[0], tmp[3].b[1], tmp[4].b[0], tmp[4].b[1], tmp[5].b[0], tmp[5].b[1], tmp[6].b[0], tmp[6].b[1], tmp[7].b[0], tmp[7].b[1], tmp[8].b[0], tmp[8].b[1] }; da->PushInBE(cl, sizeof(E), ID, E); } } uint8_t KA_TANK::SKATANKchannel::SetNewParam(uint8_t addr, uint16_t prmID, uint8_t *val) { if(TCSens1.lnk.Connected() || TCSens1Not.lnk.Connected() || TCSens2.lnk.Connected() || TCSens2Not.lnk.Connected() || TULight.lnk.Connected() || TUSound.lnk.Connected() || TURlOff.lnk.Connected() || TimeDelay.lnk.Connected() || TimeFalseAlarm.lnk.Connected()) { TCSens1.s = addr; TCSens1.Set(TSYS::getUnalign16(val)); TCSens1Not.Set(TSYS::getUnalign16(val + 2)); TCSens2.Set(TSYS::getUnalign16(val + 4)); TCSens2Not.Set(TSYS::getUnalign16(val + 6)); TULight.Set(TSYS::getUnalign16(val + 8)); TUSound.Set(TSYS::getUnalign16(val + 10)); TURlOff.Set(TSYS::getUnalign16(val + 12)); TimeDelay.Set(TSYS::getUnalign16(val + 14)); TimeFalseAlarm.Set(TSYS::getUnalign16(val + 16)); uint8_t E[19]; E[0] = addr; memcpy(E + 1, val, 18); da->PushInBE(1, sizeof(E), prmID, E); return 2 + 18; } else { return 0; } } uint8_t KA_TANK::SKATANKchannel::SetNewState(uint8_t addr, uint16_t prmID, uint8_t *val) { uint8_t rc = 0; if(Function.lnk.Connected() && State.lnk.Connected()) { if(*val < 3) { State.s = addr; State.Set(*val); Function.Set((uint8_t)0); uint8_t E[2] = { addr, State.vl }; da->PushInBE(1, sizeof(E), prmID, E); rc = 2 + 1; } } return rc; } uint8_t KA_TANK::SKATANKchannel::SetNewFunction(uint8_t addr, uint16_t prmID, uint8_t *val) { uint8_t rc = 0; if(Function.lnk.Connected() && State.lnk.Connected()) { if(((State.vl & 0x3F) != 0x2) && *val < 2) { Function.s = addr; Function.Set(*val); uint8_t E[2] = { addr, Function.vl }; da->PushInBE(1, sizeof(E), prmID, E); rc = 3; } } return rc; } KA_TANK::KA_TANK(TMdPrm& prm, uint16_t id, uint16_t n, bool has_params) : DA(prm), ID(id), count_n(n), with_params(has_params), config(0xF | (n << 4) | (2 << 10)) { mTypeFT3 = KA; chan_err.clear(); TFld * fld; mPrm.p_el.fldAdd(fld = new TFld("state", _("State"), TFld::Integer, TFld::NoWrite)); fld->setReserve("0:0"); for(int i = 0; i < count_n; i++) { chan_err.insert(chan_err.end(), SDataRec()); AddTANKchannel(i); } loadIO(true); } KA_TANK::~KA_TANK() { } void KA_TANK::AddTANKchannel(uint8_t iid) { data.push_back(SKATANKchannel(iid, this)); AddAttr(data.back().State.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:0", iid + 1)); AddAttr(data.back().Function.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:3", iid + 1)); if(with_params) { AddAttr(data.back().TCSens1.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:2", iid + 1)); AddAttr(data.back().TCSens1Not.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:2", iid + 1)); AddAttr(data.back().TCSens2.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:2", iid + 1)); AddAttr(data.back().TCSens2Not.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:2", iid + 1)); AddAttr(data.back().TULight.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:2", iid + 1)); AddAttr(data.back().TUSound.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:2", iid + 1)); AddAttr(data.back().TURlOff.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:2", iid + 1)); AddAttr(data.back().TimeDelay.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:2", iid + 1)); AddAttr(data.back().TimeFalseAlarm.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:2", iid + 1)); AddAttr(data.back().StateTCSens1.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:4", iid + 1)); AddAttr(data.back().StateTCSens1Not.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:4", iid + 1)); AddAttr(data.back().StateTCSens2.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:4", iid + 1)); AddAttr(data.back().StateTCSens2Not.lnk, TFld::Integer, TVal::DirWrite, TSYS::strMess("%d:4", iid + 1)); } } string KA_TANK::getStatus(void) { string rez; if(NeedInit) { rez = "20: Опрос каналов:"; for(int i = 1; i <= count_n; i++) { switch(chan_err[i].state) { case 0: rez += TSYS::strMess(" %d.", i); break; case 2: rez += TSYS::strMess(" %d!!!", i); break; } } } else { rez = "0: Норма"; } return rez; } void KA_TANK::loadIO(bool force) { if(mPrm.owner().startStat() && !force) { mPrm.modif(true); return; } for(int i = 0; i < count_n; i++) { loadLnk(data[i].State.lnk); loadLnk(data[i].Function.lnk); loadLnk(data[i].TCSens1.lnk); loadLnk(data[i].TCSens1Not.lnk); loadLnk(data[i].TCSens2.lnk); loadLnk(data[i].TCSens2Not.lnk); loadLnk(data[i].TULight.lnk); loadLnk(data[i].TUSound.lnk); loadLnk(data[i].TURlOff.lnk); loadLnk(data[i].TimeDelay.lnk); loadLnk(data[i].TimeFalseAlarm.lnk); loadLnk(data[i].StateTCSens1.lnk); loadLnk(data[i].StateTCSens1Not.lnk); loadLnk(data[i].StateTCSens2.lnk); loadLnk(data[i].StateTCSens2Not.lnk); } } void KA_TANK::saveIO(void) { for(int i = 0; i < count_n; i++) { saveLnk(data[i].State.lnk); saveLnk(data[i].Function.lnk); saveLnk(data[i].TCSens1.lnk); saveLnk(data[i].TCSens1Not.lnk); saveLnk(data[i].TCSens2.lnk); saveLnk(data[i].TCSens2Not.lnk); saveLnk(data[i].TULight.lnk); saveLnk(data[i].TUSound.lnk); saveLnk(data[i].TURlOff.lnk); saveLnk(data[i].TimeDelay.lnk); saveLnk(data[i].TimeFalseAlarm.lnk); saveLnk(data[i].StateTCSens1.lnk); saveLnk(data[i].StateTCSens1Not.lnk); saveLnk(data[i].StateTCSens2.lnk); saveLnk(data[i].StateTCSens2Not.lnk); } } void KA_TANK::tmHandler(void) { for(int i = 0; i < count_n; i++) { if(with_params) { data[i].UpdateParam(PackID(ID, (i + 1), 2), 1); } UpdateParam8(data[i].State, PackID(ID, (i + 1), 0), 1); UpdateParam8(data[i].Function, PackID(ID, (i + 1), 3), 1); } NeedInit = false; } uint16_t KA_TANK::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); //state if(mPrm.owner().DoCmd(&Msg)) { if(Msg.C == GOOD3) { NeedInit = false; rc = 1; for(int i = 1; i <= count_n; i++) { if(chan_err[i].state == 1) continue; Msg.L = 5; Msg.C = AddrReq; *((uint16_t *) Msg.D) = PackID(ID, i, 0); //state Msg.L += 2; *((uint16_t *) (Msg.D + 2)) = PackID(ID, i, 3); //func if(with_params) { Msg.L += 2; *((uint16_t *) (Msg.D + 4)) = PackID(ID, i, 2); //params Msg.L += 2; *((uint16_t *) (Msg.D + 6)) = PackID(ID, i, 4); //TC } if(mPrm.owner().DoCmd(&Msg)) { if(Msg.C == GOOD3) { chan_err[i].state = 1; rc = 1; } else { rc = 0; chan_err[i].state = 2; NeedInit = true; } } else { rc = 0; chan_err[i].state = 3; NeedInit = true; } } } else { rc = 0; NeedInit = true; } } break; } return rc; } uint16_t KA_TANK::HandleEvent(int64_t tm, uint8_t * D) { FT3ID ft3ID = UnpackID(TSYS::getUnalign16(D)); if(ft3ID.g != ID) return 0; uint16_t l = 0; switch(ft3ID.k) { case 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: l = 2 + count_n * 2; for(int j = 1; j <= count_n; j++) { mPrm.vlAt(TSYS::strMess("state_%d", j)).at().setI(D[j * 2 + 1], tm, true); } break; } break; default: switch(ft3ID.n) { case 0: l = 4; if(ft3ID.k > count_n) break; mPrm.vlAt(TSYS::strMess("state_%d", ft3ID.k)).at().setI(D[3], tm, true); break; case 2: l = 21; if(with_params) { if(ft3ID.k > count_n) break; mPrm.vlAt(TSYS::strMess("TCSens1_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 3), tm, true); mPrm.vlAt(TSYS::strMess("TCSens1Not_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 5), tm, true); mPrm.vlAt(TSYS::strMess("TCSens2_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 7), tm, true); mPrm.vlAt(TSYS::strMess("TCSens2Not_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 9), tm, true); mPrm.vlAt(TSYS::strMess("TULight_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 11), tm, true); mPrm.vlAt(TSYS::strMess("TUSound_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 13), tm, true); mPrm.vlAt(TSYS::strMess("TURlOff_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 15), tm, true); mPrm.vlAt(TSYS::strMess("TimeDelay_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 17), tm, true); mPrm.vlAt(TSYS::strMess("TimeFalseAlarm_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 19), tm, true); } break; case 3: l = 4; if(with_params) { if(ft3ID.k > count_n) break; mPrm.vlAt(TSYS::strMess("function_%d", ft3ID.k)).at().setI(D[3], tm, true); } break; case 4: l = 11; if(with_params) { if(ft3ID.k > count_n) break; mPrm.vlAt(TSYS::strMess("StateTCSens1_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 3), tm, true); mPrm.vlAt(TSYS::strMess("StateTCSens1Not_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 5), tm, true); mPrm.vlAt(TSYS::strMess("StateTCSens2_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 7), tm, true); mPrm.vlAt(TSYS::strMess("StateTCSens2Not_%d", ft3ID.k)).at().setI(TSYS::getUnalign16(D + 9), tm, true); } break; } break; } return l; } uint8_t KA_TANK::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: //state out[0] = 1; l = 1; break; case 1: out[0] = config >> 8; out[1] = config; l = 2; break; case 2: for(uint8_t i = 0; i < count_n; i++) { out[i * 2] = i; out[i * 2 + 1] = data[i].State.vl; } l = count_n * 2; break; } } else { if(ft3ID.k <= count_n) { switch(ft3ID.n) { case 0: out[0] = data[ft3ID.k - 1].State.s; out[1] = data[ft3ID.k - 1].State.vl; l = 2; break; case 2: out[l++] = data[ft3ID.k - 1].TCSens1.s; for(uint8_t j = 0; j < 2; j++) out[l++] = data[ft3ID.k - 1].TCSens1.b_vl[j]; for(uint8_t j = 0; j < 2; j++) out[l++] = data[ft3ID.k - 1].TCSens1Not.b_vl[j]; for(uint8_t j = 0; j < 2; j++) out[l++] = data[ft3ID.k - 1].TCSens2.b_vl[j]; for(uint8_t j = 0; j < 2; j++) out[l++] = data[ft3ID.k - 1].TCSens2Not.b_vl[j]; for(uint8_t j = 0; j < 2; j++) out[l++] = data[ft3ID.k - 1].TULight.b_vl[j]; for(uint8_t j = 0; j < 2; j++) out[l++] = data[ft3ID.k - 1].TUSound.b_vl[j]; for(uint8_t j = 0; j < 2; j++) out[l++] = data[ft3ID.k - 1].TURlOff.b_vl[j]; for(uint8_t j = 0; j < 2; j++) out[l++] = data[ft3ID.k - 1].TimeDelay.b_vl[j]; for(uint8_t j = 0; j < 2; j++) out[l++] = data[ft3ID.k - 1].TimeFalseAlarm.b_vl[j]; break; case 3: out[0] = data[ft3ID.k - 1].Function.s; out[1] = data[ft3ID.k - 1].Function.vl; l = 2; break; case 4: out[l++] = data[ft3ID.k - 1].StateTCSens1.s; for(uint8_t j = 0; j < 2; j++) out[l++] = data[ft3ID.k - 1].StateTCSens1.b_vl[j]; for(uint8_t j = 0; j < 2; j++) out[l++] = data[ft3ID.k - 1].StateTCSens1Not.b_vl[j]; for(uint8_t j = 0; j < 2; j++) out[l++] = data[ft3ID.k - 1].StateTCSens2.b_vl[j]; for(uint8_t j = 0; j < 2; j++) out[l++] = data[ft3ID.k - 1].StateTCSens2Not.b_vl[j]; break; } } } return l; } uint8_t KA_TANK::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(ft3ID.k <= count_n) { switch(ft3ID.n) { case 0: l = data[ft3ID.k - 1].SetNewState(addr, prmID, req + 2); break; case 2: l = data[ft3ID.k - 1].SetNewParam(addr, prmID, req + 2); break; case 3: l = data[ft3ID.k - 1].SetNewFunction(addr, prmID, req + 2); } } return l; } uint16_t KA_TANK::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; if((ft3ID.k >= 1) && (ft3ID.k <= count_n)) { tagMsg Msg; Msg.L = 0; Msg.C = SetData; Msg.L += SerializeUi16(Msg.D + Msg.L, PackID(ft3ID)); switch(ft3ID.n) { case 0:case 3: Msg.L += SerializeB(Msg.D + Msg.L, val.getI(0, true)); break; case 2: Msg.L += SerializeUi16(Msg.D + Msg.L, mPrm.vlAt(TSYS::strMess("TCSens1_%d", ft3ID.k)).at().getI(0, true)); Msg.L += SerializeUi16(Msg.D + Msg.L, mPrm.vlAt(TSYS::strMess("TCSens1Not_%d", ft3ID.k)).at().getI(0, true)); Msg.L += SerializeUi16(Msg.D + Msg.L, mPrm.vlAt(TSYS::strMess("TCSens2_%d", ft3ID.k)).at().getI(0, true)); Msg.L += SerializeUi16(Msg.D + Msg.L, mPrm.vlAt(TSYS::strMess("TCSens2Not_%d", ft3ID.k)).at().getI(0, true)); Msg.L += SerializeUi16(Msg.D + Msg.L, mPrm.vlAt(TSYS::strMess("TULight_%d", ft3ID.k)).at().getI(0, true)); Msg.L += SerializeUi16(Msg.D + Msg.L, mPrm.vlAt(TSYS::strMess("TUSound_%d", ft3ID.k)).at().getI(0, true)); Msg.L += SerializeUi16(Msg.D + Msg.L, mPrm.vlAt(TSYS::strMess("TURlOff_%d", ft3ID.k)).at().getI(0, true)); Msg.L += SerializeUi16(Msg.D + Msg.L, mPrm.vlAt(TSYS::strMess("TimeDelay_%d", ft3ID.k)).at().getI(0, true)); Msg.L += SerializeUi16(Msg.D + Msg.L, mPrm.vlAt(TSYS::strMess("TimeFalseAlarm_%d", ft3ID.k)).at().getI(0, true)); break; } if(Msg.L > 2) { Msg.L += 3; mPrm.owner().DoCmd(&Msg); } } return 0; }