//OpenSCADA module DAQ.BUC file: BUC.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 "BUC.h" using namespace FT3; KA_BUC::KA_BUC(TMdPrm& prm, uint16_t id) : DA(prm), ID(id), clockID(id + 1), modification(0), state(0), clockstate(0), s_state(0), config(0x2800 | (2 << 10)), clockconfig(0x01 | (1 << 10)) { mTypeFT3 = KA; TFld * fld; mPrm.p_el.fldAdd(fld = new TFld("state", _("State"), TFld::Integer, TVal::DirWrite)); fld->setReserve("0:0:0"); mPrm.p_el.fldAdd(fld = new TFld("config", _("Configuration"), TFld::Integer, TFld::NoWrite)); fld->setReserve("0:1:0"); mPrm.p_el.fldAdd(fld = new TFld("modification", _("Modification"), TFld::Integer, TFld::NoWrite)); fld->setReserve("0:2:0"); mPrm.p_el.fldAdd(fld = new TFld("sttimer", _("Timer state"), TFld::Integer, TFld::NoWrite)); fld->setReserve("0:0:1"); mPrm.p_el.fldAdd(fld = new TFld("curdt", _("Current datetime"), TFld::String, TVal::DirWrite | TVal::DirRead)); fld->setReserve("0:2:1"); mPrm.p_el.fldAdd(fld = new TFld("stopdt", _("Stop datetime"), TFld::String, TFld::NoWrite)); fld->setReserve("0:3:1"); mPrm.p_el.fldAdd(fld = new TFld("reset", _("Hard Reset"), TFld::Boolean, TVal::DirWrite)); fld->setReserve("1:0:0"); mPrm.p_el.fldAdd(fld = new TFld("resetchn", _("Channel reset"), TFld::Boolean, TVal::DirWrite)); fld->setReserve("1:1:0"); mPrm.p_el.fldAdd(fld = new TFld("resetdata", _("Data reset"), TFld::Boolean, TVal::DirWrite)); fld->setReserve("1:2:0"); //fld->setReserve("1:0:3"); } KA_BUC::~KA_BUC() { } string KA_BUC::getStatus(void) { string rez; switch(mPrm.vlAt("state").at().getI(0, true)) { case KA_BUC_HardReset: rez = _("10: Hard reset"); break; case KA_BUC_Normal: rez = _("0: Normal"); break; case KA_BUC_SoftReset: rez = _("11: Soft reset"); break; case KA_BUC_Setup: rez = _("12: Setup"); case KA_BUC_Start: rez = _("13: Startup"); break; } return rez; } void KA_BUC::tmHandler(void) { NeedInit = false; } uint16_t KA_BUC::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_BUC_HardReset: rc = BlckStateHardReset; break; case KA_BUC_Normal: rc = BlckStateNormal; break; case KA_BUC_SoftReset: rc = BlckStateSoftReset; break; case KA_BUC_Setup: case KA_BUC_Start: rc = BlckStateSetup; break; } } return rc; } uint16_t KA_BUC::SetupClock(void) { uint16_t rc; tagMsg Msg; Msg.L = 6; Msg.C = SetData; *((uint16_t *) Msg.D) = PackID(ID, 0, 0); //state Msg.D[2] = 0x80; rc = mPrm.owner().DoCmd(&Msg); if(rc == GOOD2 || rc == GOOD3) { time_t rawtime; time(&rawtime); Msg.L = 10; Msg.C = SetData; *((uint16_t *) Msg.D) = PackID(1, 0, 2); //current time mPrm.owner().Time_tToDateTime(Msg.D + 2, rawtime); rc = mPrm.owner().DoCmd(&Msg); } return rc; } uint16_t KA_BUC::Start(void) { tagMsg Msg; uint16_t rc = GOOD2; Msg.L = 6; Msg.C = SetData; *((uint16_t *) Msg.D) = PackID(ID, 0, 0); //state Msg.D[2] = 0x01; return mPrm.owner().DoCmd(&Msg); } uint16_t KA_BUC::RefreshData(void) { tagMsg Msg; Msg.L = 3 + 2 * 6; Msg.C = AddrReq; *((uint16_t *) Msg.D) = PackID(ID, 0, 0); //state *((uint16_t *) (Msg.D + 2)) = PackID(ID, 0, 1); //configuration *((uint16_t *) (Msg.D + 4)) = PackID(ID, 0, 2); //modification *((uint16_t *) (Msg.D + 6)) = PackID(1, 0, 0); //timer state *((uint16_t *) (Msg.D + 8)) = PackID(1, 0, 2); //current time *((uint16_t *) (Msg.D + 10)) = PackID(1, 0, 3); //uptime return mPrm.owner().DoCmd(&Msg); } uint16_t KA_BUC::Task(uint16_t uc) { switch(mPrm.vlAt("state").at().getI(0, true)) { case KA_BUC_HardReset: mPrm.owner().SetCntrState(StateHardReset); break; case KA_BUC_Normal: break; case KA_BUC_SoftReset: mPrm.owner().SetCntrState(StateSoftReset); break; case KA_BUC_Setup: case KA_BUC_Start: mPrm.owner().SetCntrState(StateUnknown); break; } return 0; } uint16_t KA_BUC::HandleEvent(int64_t tm, uint8_t *D) { FT3ID ft3ID = UnpackID(TSYS::getUnalign16(D)); uint16_t l = 0; if(ft3ID.g == ID) { switch(ft3ID.k) { case 0: switch(ft3ID.n) { case 0: s_state = D[2]; state = D[3]; mPrm.vlAt("state").at().setI(state, tm, true); l = 4; break; case 1: config = TSYS::getUnalign16(D + 2); mPrm.vlAt("config").at().setI(config, tm, true); l = 4; break; case 2: modification = TSYS::getUnalign16(D + 2); mPrm.vlAt("modification").at().setI(modification, tm, true); l = 4; break; } break; } } if(ft3ID.g == clockID) { time_t t; switch(ft3ID.k) { case 0: switch(ft3ID.n) { case 0: clockstate = D[2]; mPrm.vlAt("sttimer").at().setI(clockstate, tm, true); l = 3; break; case 1: clockconfig = TSYS::getUnalign16(D + 2); l = 4; break; case 2: t = mPrm.owner().DateTimeToTime_t(D + 3); mPrm.vlAt("curdt").at().setS(atm2s(t, "%d.%m.%Y %H:%M:%S"), tm, true); l = 8; break; case 3: t = mPrm.owner().DateTimeToTime_t(D + 2); mPrm.vlAt("stopdt").at().setS(atm2s(t, "%d.%m.%Y %H:%M:%S"), tm, true); l = 7; break; } break; } } return l; } uint16_t KA_BUC::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 = s2i(TSYS::strParse(val.fld().reserve(), 0, ":", &off)); tagMsg Msg; Msg.L = 0; Msg.C = SetData; *((uint16_t *) Msg.D) = PackID(ft3ID); if(ft3ID.g == ID) { switch(ft3ID.k) { case 0: switch(ft3ID.n) { case 0: Msg.L = 6; Msg.D[2] = val.getI(0, true); break; } break; case 1: switch(ft3ID.n) { case 0: Msg.L = 3; Msg.C = Reset; break; case 1: Msg.L = 3; Msg.C = ResetChan; break; case 2: Msg.L = 3; Msg.C = ResData2; break; } val.setB(0, 0, true); break; } } if(ft3ID.g == clockID) { switch(ft3ID.k) { case 0: switch(ft3ID.n) { case 2: struct tm tm_tm; strptime(val.getS(0, true).c_str(), "%d.%m.%Y %H:%M:%S", &tm_tm); Msg.L = 10; mPrm.owner().Time_tToDateTime(Msg.D + 2, mktime(&tm_tm)); break; } break; } } if(Msg.L) mPrm.owner().DoCmd(&Msg); return 0; } void KA_BUC::vlGet(TVal &val) { if(val.name() == "curdt") { tagMsg Msg; Msg.L = 0; Msg.C = AddrReq; Msg.L += SerializeUi16(Msg.D + Msg.L, PackID(1, 0, 2)); //current time Msg.L += SerializeUi16(Msg.D + Msg.L, PackID(1, 0, 3)); //uptime Msg.L += 3; mPrm.owner().DoCmd(&Msg); } } uint8_t KA_BUC::cmdGet(uint16_t prmID, uint8_t * out) { FT3ID ft3ID = UnpackID(prmID); time_t rawtime; uint l = 0; unsigned long val = 0; if(ft3ID.g == ID) { switch(ft3ID.k) { case 0: switch(ft3ID.n) { case 0: out[0] = s_state; out[1] = state; l = 2; break; case 1: out[0] = config & 0xFF; out[1] = (config >> 8) & 0xFF; l = 2; break; case 2: out[0] = modification & 0xFF; out[1] = (modification >> 8) & 0xFF; l = 2; break; } break; } } if(ft3ID.g == clockID) { switch(ft3ID.k) { case 0: switch(ft3ID.n) { case 0: out[0] = clockstate; l = 1; break; case 1: out[0] = clockconfig & 0xFF; out[1] = (clockconfig >> 8) & 0xFF; l = 2; break; case 2: out[0] = s_state; time(&rawtime); mPrm.owner().Time_tToDateTime(out + 1, rawtime); l = 6; break; case 3: time(&rawtime); FILE *f = fopen("/proc/uptime", "r"); if((f != NULL) && (fscanf(f, "%lu", &val) == 1)) { rawtime -= val; } fclose(f); mPrm.owner().Time_tToDateTime(out, rawtime); l = 5; break; } break; } } return l; } uint8_t KA_BUC::cmdSet(uint8_t * req, uint8_t addr) { uint16_t prmID = TSYS::getUnalign16(req); FT3ID ft3ID = UnpackID(prmID); uint8_t l = 0; time_t rawtime; if(ft3ID.g == ID) { switch(ft3ID.k) { case 0: switch(ft3ID.n) { case 0: if(req[2] & 0x81) { if(state != req[2]) { if(req[2] == 1) { if((state == 0x80) || (state == 0x02)) { state = 1; } else { state = 0x81; } } else { state = req[2]; } } s_state = addr; uint8_t E[2] = { addr, state }; PushInBE(1, 2, prmID, E); l = 3; } break; } break; } } if(ft3ID.g == clockID) { switch(ft3ID.k) { case 0: switch(ft3ID.n) { case 2: s_state = addr; state = clockstate = 1; rawtime = mPrm.owner().DateTimeToTime_t(req + 2); stime(&rawtime); l = 7; break; } break; } } return l; } B_BUC::B_BUC(TMdPrm& prm, uint16_t id, uint16_t modif) : DA(prm), ID(id), mod_KP(modif), state(2), stateWatch(1), s_tm(0), wt1(0), wt2(0), s_wt1(0), s_wt2(0) { mTypeFT3 = GRS; TFld * fld; mPrm.p_el.fldAdd(fld = new TFld("state", _("State"), TFld::Integer, TFld::NoWrite)); fld->setReserve("0:0"); mPrm.p_el.fldAdd(fld = new TFld("modification", _("Modification"), TFld::Integer, TFld::NoWrite)); fld->setReserve("0:1"); mPrm.p_el.fldAdd(fld = new TFld("sttimer", _("Timer state"), TFld::Integer, TFld::NoWrite)); fld->setReserve("1:0"); mPrm.p_el.fldAdd(fld = new TFld("curdt", _("Current datetime"), TFld::String, TVal::DirWrite)); fld->setReserve("1:1"); mPrm.p_el.fldAdd(fld = new TFld("stopdt", _("Stop datetime"), TFld::String, TFld::NoWrite)); fld->setReserve("1:2"); mPrm.p_el.fldAdd(fld = new TFld("dl1", _("Delay 1"), TFld::Integer, TVal::DirWrite)); fld->setReserve("2:1"); mPrm.p_el.fldAdd(fld = new TFld("dl2", _("Delay 2"), TFld::Integer, TVal::DirWrite)); fld->setReserve("2:2"); } B_BUC::~B_BUC() { } string B_BUC::getStatus(void) { string rez; if(NeedInit) { rez = "20: Опрос"; } else { rez = "0: Норма"; } return rez; } void B_BUC::tmHandler(void) { NeedInit = false; } uint16_t B_BUC::Task(uint16_t uc) { tagMsg Msg; uint16_t rc = 0; switch(uc) { case TaskRefresh: Msg.L = 17; Msg.C = AddrReq; *((uint16_t *) Msg.D) = PackID(ID, 0, 0); //state *((uint16_t *) (Msg.D + 2)) = PackID(ID, 0, 1); //modification *((uint16_t *) (Msg.D + 4)) = PackID(ID, 1, 0); //timer state *((uint16_t *) (Msg.D + 6)) = PackID(ID, 1, 1); //current time *((uint16_t *) (Msg.D + 8)) = PackID(ID, 1, 2); //uptime *((uint16_t *) (Msg.D + 10)) = PackID(ID, 2, 1); //delay 1 *((uint16_t *) (Msg.D + 12)) = PackID(ID, 2, 2); //delay 2 if(mPrm.owner().DoCmd(&Msg)) { if(Msg.C == GOOD3) { if(mPrm.vlAt("state").at().getI(0, true) != 0) { if(Task(TaskSetParams) == 1) { rc = 1; } } else { rc = 1; } } } if(rc) NeedInit = false; break; case TaskSetParams: time_t rawtime; time(&rawtime); Msg.L = 10; Msg.C = SetData; *((uint16_t *) Msg.D) = PackID(ID, 1, 1); mPrm.owner().Time_tToDateTime(Msg.D + 2, rawtime); //current time mPrm.owner().DoCmd(&Msg); if(Msg.C == GOOD2) { rc = 1; } break; case TaskIdle: if(mPrm.vlAt("state").at().getI(0, true) != 0) { rc = 2; } break; } return rc; } uint16_t B_BUC::HandleEvent(int64_t tm, uint8_t * D) { FT3ID ft3ID = UnpackID(TSYS::getUnalign16(D)); if(ft3ID.g != ID) return 0; uint16_t l = 0; time_t t; switch(ft3ID.k) { case 0: switch(ft3ID.n) { case 0: state = D[2]; mPrm.vlAt("state").at().setI(state, tm, true); l = 3; break; case 1: mod_KP = TSYS::getUnalign16(D + 2); mPrm.vlAt("modification").at().setI(mod_KP, tm, true); l = 4; break; } break; case 1: switch(ft3ID.n) { case 0: stateWatch = D[2]; mPrm.vlAt("sttimer").at().setI(stateWatch, tm, true); l = 3; break; case 1: t = mPrm.owner().DateTimeToTime_t(D + 3); mPrm.vlAt("curdt").at().setS(atm2s(t, "%d.%m.%Y %H:%M:%S"), tm, true); l = 8; break; case 2: t = mPrm.owner().DateTimeToTime_t(D + 2); mPrm.vlAt("stopdt").at().setS(atm2s(t, "%d.%m.%Y %H:%M:%S"), tm, true); l = 7; break; } break; case 2: switch(ft3ID.n) { case 1: s_wt1 = D[2]; wt1 = D[3]; mPrm.vlAt("dl1").at().setI(wt1, tm, true); l = 4; break; case 2: s_wt2 = D[2]; wt2 = D[3]; mPrm.vlAt("dl2").at().setI(wt2, tm, true); l = 4; break; } break; } return l; } uint16_t B_BUC::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 = s2i(TSYS::strParse(val.fld().reserve(), 0, ":", &off)); tagMsg Msg; Msg.L = 0; Msg.C = SetData; *((uint16_t *) Msg.D) = PackID(ft3ID); switch(ft3ID.k) { case 1: switch(ft3ID.n) { case 1: struct tm tm_tm; strptime(val.getS(0, true).c_str(), "%d.%m.%Y %H:%M:%S", &tm_tm); Msg.L = 10; mPrm.owner().Time_tToDateTime(Msg.D + 2, mktime(&tm_tm)); break; } break; case 2: switch(ft3ID.n) { case 1: case 2: tagMsg Msg; Msg.L = 6; Msg.D[2] = val.getI(0, true); break; } break; } if(Msg.L) mPrm.owner().DoCmd(&Msg); return 0; } uint8_t B_BUC::cmdGet(uint16_t prmID, uint8_t * out) { FT3ID ft3ID = UnpackID(prmID); if(ft3ID.g != ID) return 0; uint l = 0; time_t rawtime; unsigned long val = 0; switch(ft3ID.k) { case 0: switch(ft3ID.n) { case 0: out[0] = state; l = 1; break; case 1: out[0] = mod_KP & 0xFF; out[1] = (mod_KP >> 8) & 0xFF; l = 2; break; } break; case 1: switch(ft3ID.n) { case 0: out[0] = stateWatch; l = 1; break; case 1: out[0] = s_tm; time(&rawtime); mPrm.owner().Time_tToDateTime(out + 1, rawtime); l = 6; break; case 2: time(&rawtime); FILE *f = fopen("/proc/uptime", "r"); if((f != NULL) && (fscanf(f, "%lu", &val) == 1)) { rawtime -= val; } fclose(f); mPrm.owner().Time_tToDateTime(out, rawtime); l = 5; break; } break; case 2: switch(ft3ID.n) { /* case 0: out[0] = s_tlg; do z[l + 3] = tlg_buf[l]; while (tlg_buf[l++]); l += 3; break;*/ case 1: out[0] = s_wt1; out[1] = wt1; l = 2; break; case 2: out[0] = s_wt2; out[1] = wt2; l = 2; break; } break; } return l; } uint8_t B_BUC::cmdSet(uint8_t * req, uint8_t addr) { uint16_t prmID = TSYS::getUnalign16(req); FT3ID ft3ID = UnpackID(prmID); if(ft3ID.g != ID) return 0; uint8_t l = 0; time_t rawtime; switch(ft3ID.k) { case 1: switch(ft3ID.n) { case 1: s_tm = addr; state = stateWatch = 0; rawtime = mPrm.owner().DateTimeToTime_t(req + 2); stime(&rawtime); l = 7; break; } break; } return l; }