#include "modelbahn.h" #include "turnout.h" Turnouts::Turnouts() { changed = 0; turnouts = (Turnout*) malloc(sizeof(Turnout)*TURNOUTS_MAX); max = TURNOUTS_MAX; }; Turnouts::~Turnouts() { free (turnouts); max = 0; turnouts = NULL; }; int Turnouts::Lock() { if (pthread_mutex_lock(&mtx) == 0) return 1; else return 0; } int Turnouts::UnLock() { if (pthread_mutex_unlock(&mtx) == 0) return 1; else return 0; } JSONParse Turnouts::_GetJSON(int idx) { JSONParse json; JSONElement je; string s = ""; json.Clear(); s = turnouts[idx].name; json.AddObject("name", s); s = turnouts[idx].ifname; json.AddObject("ifname", s); json.AddObject("addr", turnouts[idx].addr); json.AddObject("activetimeout", turnouts[idx].activetimeout); json.AddObject("flags", turnouts[idx].flags); return json; }; JSONParse Turnouts::GetJSON(string name) { int i; JSONParse jp; jp.Clear(); Lock(); for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) { if (name.compare(turnouts[i].name) == 0) { jp = _GetJSON(i); } } UnLock(); return jp; }; void Turnouts::GetJSONAll(JSONParse *json) { int i, cnt; JSONElement je; Lock(); // // write all railway data // create json object array manualy je.type = JSON_T_ARRAY; je.name = "turnouts"; for (cnt = 0, i = 0; i < max; i++) if (turnouts[i].name[0] != 0) { if (cnt != 0) je.value += ","; // not first element je.value += _GetJSON(i).ToString(); cnt++; } json->AddObject(je); UnLock(); }; Turnout Turnouts::GetTurnoutFromJSON(JSONParse *j) { Turnout to; string s; to.name[0] = 0; to.ifname[0] = 0; to.addr = 0; to.activetimeout = TURNOUT_DEFAULT_ACTIVETIMEOUT; // default active timeout in MS to.flags = 0; j->GetValue("name", &s); strncpy (to.name, s.c_str(), REFERENCENAME_LEN); j->GetValue("ifname", &s); strncpy (to.ifname, s.c_str(), REFERENCENAME_LEN); j->GetValueInt("addr", &to.addr); j->GetValueInt("activetimeout", &to.activetimeout); j->GetValueInt("flags", &to.flags); return to; }; int Turnouts::Change(Turnout *to) { int i; int ifree = -1; Lock(); for (i = 0; i < max; i++) { if (turnouts[i].name[0] != 0) { // found element if (strncmp(turnouts[i].name, to->name, REFERENCENAME_LEN) == 0) { ifree = i; break; } } else if (ifree == -1) ifree = i; } // element not found add new element if (ifree != -1 && ifree < max) { turnouts[ifree] = *to; strncpy (turnouts[ifree].name, to->name, REFERENCENAME_LEN); strncpy (turnouts[ifree].ifname, to->ifname, REFERENCENAME_LEN); turnouts[ifree].activetimeout = to->activetimeout; } changed = 1; UnLock(); return 1; }; int Turnouts::Delete(string name) { int i; Lock(); for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) { if (name.compare(turnouts[i].name) == 0) { turnouts[i].name[0] = 0; turnouts[i].ifname[0] = 0; turnouts[i].addr = 0; turnouts[i].flags = 0; turnouts[i].activetimeout = TURNOUT_DEFAULT_ACTIVETIMEOUT; changed = 1; break; } } UnLock(); return 1; }; int Turnouts::Set(string name, int value) { int i; // Lock(); for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) { if (name.compare(turnouts[i].name) == 0) { debug (0, "Turnout::Set: Name:%s Flags:%d[%c%c%c] Value:%d", name.c_str(), turnouts[i].flags, (turnouts[i].flags & TURNOUT_F_INVERSE) ? 'I' : '-', (turnouts[i].flags & TURNOUT_F_ACTIVE) ? 'A' : '-', (turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-', value); if (turnouts[i].flags & TURNOUT_F_INVERSE) server->interfaces.SetTurnout(&turnouts[i], !value, 1); // motor on else server->interfaces.SetTurnout(&turnouts[i], value, 1); // motor on gettimeofday (&turnouts[i].activatetime, NULL); changed = 1; break; } } UnLock(); return 1; }; // // got some data from bus void Turnouts::SetFromBus(string ifname, int addr, int value) { int i; JSONParse jp; debug (0, "Turnouts::SetFromBus Interface:%s, addr: %d, value:%d", ifname.c_str(), addr, value); for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) { if (ifname.compare(turnouts[i].ifname) == 0 && turnouts[i].addr == addr) { debug (0, "Turnout::SetFromBus Name:%s Flags:%d[%c%c%c]", turnouts[i].name, turnouts[i].flags, (turnouts[i].flags & TURNOUT_F_INVERSE) ? 'I' : '-', (turnouts[i].flags & TURNOUT_F_ACTIVE) ? 'A' : '-', (turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-'); // if (value) turnouts[i].flags |= TURNOUT_F_ACTIVE; // else turnouts[i].flags &= ~TURNOUT_F_ACTIVE; if (turnouts[i].flags & TURNOUT_F_INVERSE) { if (value) turnouts[i].flags &= ~TURNOUT_F_TURNOUT; else turnouts[i].flags |= TURNOUT_F_TURNOUT; } else { if (value) turnouts[i].flags |= TURNOUT_F_TURNOUT; else turnouts[i].flags &= ~TURNOUT_F_TURNOUT; } debug (0, "Turnout::SetFromBus Name:%s Flags:%d[%c%c%c]", turnouts[i].name, turnouts[i].flags, (turnouts[i].flags & TURNOUT_F_INVERSE) ? 'I' : '-', (turnouts[i].flags & TURNOUT_F_ACTIVE) ? 'A' : '-', (turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-'); jp.AddObject("turnout", _GetJSON(i)); if(network) network->ChangeListPushToAll(jp.ToString()); } } }; // // this loop is important: Turnout motors needs to be deactivated after a short time // void Turnouts::Loop() { int i; struct timeval curtime; gettimeofday(&curtime, NULL); Lock(); for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) { if (turnouts[i].flags & TURNOUT_F_ACTIVE) { // // motor still active check timeout and deactivate int timediff = (1000 * (curtime.tv_sec - turnouts[i].activatetime.tv_sec)) + ((curtime.tv_usec - turnouts[i].activatetime.tv_usec) / 1000); if (timediff < 0) gettimeofday (&turnouts[i].activatetime, NULL); // debug (0, "%s:%d timediff: %d", __FILE__, __LINE__, timediff); if (timediff > turnouts[i].activetimeout) { int active = turnouts[i].flags & TURNOUT_F_TURNOUT; if (turnouts[i].flags & TURNOUT_F_INVERSE) server->interfaces.SetTurnout(&turnouts[i], !active, 0); // motor on else server->interfaces.SetTurnout(&turnouts[i], active, 0); // motor on turnouts[i].flags &= ~TURNOUT_F_ACTIVE; } } } UnLock(); };