///////////////////////////////////////////////////////////////////////////////// // // guivalues.cc is part of TestModbus-Server. // ///////////////////////////////////////////////////////////////////////////////// // // // show all variables and the value // // #include #include #include "gui.h" #include "config.h" #include "mbsconfig.h" #include "modbussrv.h" #include "guivalues.h" void Value_ModStore(GtkTreeModel *model, GtkTreeIter *iter, GuiValue *g); extern GtkBuilder *_builder_; // work around for threads GuiValue::GuiValue() { sim = ""; name = ""; type = ""; fc = 0; reg = 0; }; GuiValue::~GuiValue() { }; // walk throught the registers and draw them.. if unknown//not yet set check for auto add void Values_ChangeRegs (int fc, int regstart, int count, ModbusRegister *r) { int autoadd = 0; int reg, idx; GtkWidget *cb_autovalue = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "conf_autoaddvalues")); GtkWidget *vars = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vars_tv")); GtkTreeIter iter; GtkTreeModel *model; gboolean result; gchar *v_name = NULL; gchar *v_fc = NULL; gchar *v_reg = NULL; gchar *v_type = NULL; gchar *v_sim = NULL; int found = 0; int regsize = 1; model = gtk_tree_view_get_model(GTK_TREE_VIEW(vars)); autoadd = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cb_autovalue)); for (idx = 0, reg = regstart; idx < count; reg++, idx++) { for (found = 0, result = gtk_tree_model_get_iter_first(model, &iter); found == 0 && result == TRUE; result = gtk_tree_model_iter_next(model, &iter)) { gtk_tree_model_get (model, &iter, VALDATA_COL_NAME, &v_name, VALDATA_COL_FC, &v_fc, VALDATA_COL_REGSTART, &v_reg, VALDATA_COL_TYPE, &v_type, VALDATA_COL_SIM, &v_sim, -1); if (v_name == NULL || v_reg == NULL || v_fc == NULL || v_type == NULL) { if (v_name != NULL) g_free(v_name); if (v_reg != NULL) g_free(v_reg); if (v_fc != NULL) g_free(v_fc); if (v_type != NULL) g_free(v_type); if (v_sim != NULL) g_free(v_sim); break; } regsize = Value_GetSize(v_type); if (atoi(v_fc) == fc && reg >= atoi(v_reg) && reg < (atoi(v_reg) + regsize)) { found = 1; GuiValue v; v.name = v_name; v.fc = atoi(v_fc); v.reg = atoi(v_reg); v.type = v_type; v.sim = v_sim; Value_Set (&v); } g_free(v_name); g_free(v_fc); g_free(v_reg); g_free(v_sim); g_free(v_type); } if (autoadd && found == 0) { GuiValue v; v.name = "_auto_FC" + std::to_string(fc) + "_REG_" + std::to_string (reg); v.sim = "NONE"; v.fc = fc; v.reg = reg; if (v.fc == 1 || v.fc == 2) v.type = "BOOL"; else v.type = "WORD"; Value_Set (&v); } } }; std::string findparm(std::string t, std::string parm) { std::string res = ""; string::size_type i = t.find(parm+"="); string::size_type j,k; if (i != string::npos) { res = t.substr (i, string::npos); j = res.find("="); k = res.find(";"); if (k != string::npos) k = k -j -1; if (j != string::npos) res = res.substr(j+1, k); } return res; } int Value_Simulation(GuiValue *v) { struct timeval tv; string s; gettimeofday (&tv, NULL); string sim = v->sim.substr(0, v->sim.find(";")); if (sim.compare("PULSE") == 0) { int ton = 10; s = findparm(v->sim, "ton"); if(s.length()>0) ton = atoi(s.c_str()); int toff = 50; s = findparm(v->sim, "toff"); if(s.length()>0) toff = atoi(s.c_str()); int td = ton +toff; td = tv.tv_sec % td; if (td <= ton) v->value = "true"; else v->value = "false"; return 1; } else if (sim.compare("SIN") == 0) { int td = 60; s = findparm(v->sim, "t"); if(s.length()>0) td = atoi(s.c_str()); float min = -100; s = findparm(v->sim, "min"); if(s.length()>0) min = atof(s.c_str()); float max = 100; s = findparm(v->sim, "max"); if(s.length()>0) max = atof(s.c_str()); float t = ((float)(tv.tv_sec % td)) + (((float)tv.tv_usec) / 1000000); t = 4.0 * t * M_PI / td; v->value = std::to_string((0.5*(max-min)*sin(t))+(min+max)*0.5); return 1; } else if (sim.compare("SAW") == 0) { int td = 60; s = findparm(v->sim, "t"); if(s.length()>0) td = atoi(s.c_str()); float min = -100; s = findparm(v->sim, "min"); if(s.length()>0) min = atof(s.c_str()); float max = 100; s = findparm(v->sim, "max"); if(s.length()>0) max = atof(s.c_str()); float t = ((float)(tv.tv_sec % td)) + (((float)tv.tv_usec) / 1000000); t = t / td; v->value = std::to_string((max-min)*t+min); return 1; } return 0; }; gboolean Value_Loop(gpointer data) { GtkWidget *vars = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vars_tv")); GtkTreeIter iter; GtkTreeModel *model; gboolean result; gchar *v_name = NULL; gchar *v_type = NULL; gchar *v_value = NULL; gchar *v_sim = NULL; gchar *v_fc = NULL; gchar *v_reg = NULL; GuiValue v; int changed = 0; model = gtk_tree_view_get_model(GTK_TREE_VIEW(vars)); for (result = gtk_tree_model_get_iter_first(model, &iter); result == TRUE; result = gtk_tree_model_iter_next(model, &iter)) { gtk_tree_model_get (model, &iter, VALDATA_COL_NAME, &v_name, VALDATA_COL_TYPE, &v_type, VALDATA_COL_SIM, &v_sim, VALDATA_COL_VALUE, &v_value, VALDATA_COL_FC, &v_fc, VALDATA_COL_REGSTART, &v_reg, -1); if (v_name == NULL) break; GuiValue v; v.name = v_name; v.fc = atoi(v_fc); v.reg = atoi(v_reg); v.type = v_type; v.sim = v_sim; changed = Value_Simulation(&v); if (changed) { uint16_t regvals[4]; int regstowrite = 1; if (Value_SetValue(v.value, v.type, v.fc, ®stowrite, regvals)) { modbussrv.SetRegValue(v.fc, v.reg, regstowrite, (uint16_t*)regvals); } gtk_list_store_set(GTK_LIST_STORE(model), &iter, VALDATA_COL_NAME, v.name.c_str(), VALDATA_COL_FC, std::to_string(v.fc).c_str(), VALDATA_COL_REGSTART, std::to_string(v.reg).c_str(), VALDATA_COL_TYPE, v.type.c_str(), VALDATA_COL_VALUE, Value_GetValue(v.fc, v.reg, v.type).c_str(), VALDATA_COL_SIM, v.sim.c_str(), -1); } g_free(v_name); g_free(v_type); g_free(v_sim); g_free(v_value); g_free(v_reg); g_free(v_fc); } return TRUE; // continue timer } void Value_Set(GuiValue *g) { GtkWidget *vars = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vars_tv")); GtkTreeIter iter; GtkTreeModel *model; gboolean result; gchar *v_name = NULL; int changed = 0; model = gtk_tree_view_get_model(GTK_TREE_VIEW(vars)); for (result = gtk_tree_model_get_iter_first(model, &iter); result == TRUE && changed == 0; result = gtk_tree_model_iter_next(model, &iter)) { gtk_tree_model_get (model, &iter, VALDATA_COL_NAME, &v_name, -1); if (v_name == NULL) break; if (strcmp(v_name, g->name.c_str()) == 0) { Value_ModStore(model, &iter, g); changed = 1; break; } g_free(v_name); } if (changed == 0) Value_Add(g); } int Value_GetSize(std::string type) { if (type.compare("WORD") == 0) return 1; if (type.compare("DWORD") == 0) return 2; if (type.compare("FLOAT") == 0) return 2; if (type.compare("DWORD_SWAP") == 0) return 2; if (type.compare("FLOAT_SWAP") == 0) return 2; return 1; } void Value_Add(GuiValue *g) { GtkWidget *vars = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vars_tv")); GtkTreeIter iter; GtkTreeModel *model; int count; model = gtk_tree_view_get_model(GTK_TREE_VIEW(vars)); gtk_list_store_append (GTK_LIST_STORE(model), &iter); Value_ModStore(model, &iter, g); count = Value_GetSize(g->type); modbussrv.Enable(g->fc, g->reg, count, 1); MBData_Enable(g->fc, g->reg, count, 1); } void Value_ModStore(GtkTreeModel *model, GtkTreeIter *iter, GuiValue *g) { g->value = Value_GetValue(g->fc, g->reg, g->type); gtk_list_store_set(GTK_LIST_STORE(model), iter, VALDATA_COL_NAME, g->name.c_str(), VALDATA_COL_FC, std::to_string(g->fc).c_str(), VALDATA_COL_REGSTART, std::to_string(g->reg).c_str(), VALDATA_COL_TYPE, g->type.c_str(), VALDATA_COL_VALUE, Value_GetValue(g->fc, g->reg, g->type).c_str(), VALDATA_COL_SIM, g->sim.c_str(), -1); }; /////////////////////////////////////////////////// // return valuze as string std::string Value_GetValue(int fc, int reg, string type) { std::string result = ""; if (fc == 1 || fc == 2) { if (modbusdata[fc-1][reg]) result = "true"; else result = "false"; } else if (fc == 3 || fc == 4) { if (type.compare ("WORD") == 0) result = std::to_string(modbusdata[fc-1][reg]); else if (type.compare ("FLOAT") == 0) { uint8_t data[4]; float *f = (float*)&data; memcpy (data, &modbusdata[fc-1][reg], 2); memcpy (data+2, &modbusdata[fc-1][reg+1], 2); result = std::to_string(*f); } else if (type.compare ("FLOAT_SWAP") == 0) { uint8_t data[4]; float *f = (float*)&data; memcpy (data, &modbusdata[fc-1][reg+1], 2); memcpy (data+2, &modbusdata[fc-1][reg], 2); result = std::to_string((double)*f); } else if (type.compare ("DWORD") == 0) { uint8_t data[4]; uint32_t *f = (uint32_t*)&data; memcpy (data, &modbusdata[fc-1][reg], 2); memcpy (data+2, &modbusdata[fc-1][reg+1], 2); result = std::to_string(*f); } else if (type.compare ("DWORD_SWAP") == 0) { uint8_t data[4]; uint32_t *f = (uint32_t*)&data; memcpy (data, &modbusdata[fc-1][reg+1], 2); memcpy (data+2, &modbusdata[fc-1][reg], 2); result = std::to_string(*f); } else if (type.compare ("BOOL") == 0) { int c; for (result = "", c = 0; c < 16; c++) { if (modbusdata[fc-1][reg] & (1<