/// <summary> /// This method runs in a separate thread and continually polls Thingsboard for /// RPC calls. /// </summary> private async void rpcListenerProc() { ThingsboardProperties tbp = ThingsboardProperties.getInstance(); while (true) { try { string url = $"https://{tbp.ThingsboardHost}:{tbp.ThingsboardPort}/api/v1/{tbp.PumpControllerAccessToken}/rpc?timeout=20000"; HttpResponseMessage response = await Program.httpClient.GetAsync(url); string responseBody = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { // Synchronise access to the RpcCommand field due to two // different threads working with it. lock (this) { rpcCommand = JObject.Parse(responseBody); form.AddToLog("Downlink received but not yet delivered: " + responseBody); if ((Boolean)rpcCommand["params"]["timerOn"]) { form.SetTimer((String)rpcCommand["params"]["timer"]); } else { form.SetTimer("0"); } } } } catch (HttpRequestException e) { form.AddToLog("Exception Caught!"); form.AddToLog($"Message :{e.Message}"); } } }
private void MainForm_Load(object sender, EventArgs e) { commandPoller.form = this; // When binding a control property to a data source based upon a simple object, the args to the X.DataBindings.Add method are: // 1. The name of the control's property being bound, eg "Text" or "Checked". // 2. A reference to the binding source. // 3. The property of the object used to get the value for the control's property. // 4. Something about the value being reformatted. // 5. A flag to push changes made to the control's property back to the object so if the user changes the text or checks/unchecks a // box, this is reflected in the bound object's properties. // This binds the Thingsboard properties fields to the ThingsboardProperties singleton instance. The initial values of the text boxes // are set from the singletons properties but after that the bindings are from the text boxes to the singleton. tbPropsBindingSource = new BindingSource(); tbPropsBindingSource.DataSource = ThingsboardProperties.getInstance(); txtThingsboardHost.DataBindings.Add("Text", tbPropsBindingSource, "ThingsboardHost", false, DataSourceUpdateMode.OnPropertyChanged); txtThingsboardPort.DataBindings.Add("Text", tbPropsBindingSource, "ThingsboardPort", false, DataSourceUpdateMode.OnPropertyChanged); txtLevelSensorAccessCode.DataBindings.Add("Text", tbPropsBindingSource, "LevelSensorAccessToken", false, DataSourceUpdateMode.OnPropertyChanged); txtPumpControllerAccessCode.DataBindings.Add("Text", tbPropsBindingSource, "PumpControllerAccessToken", false, DataSourceUpdateMode.OnPropertyChanged); // Bind the level sensor text fields to the tankMessage properties. This is a one-way binding for now. // Update on validation is important here because we're working with floats. If the value doesn't parse // correctly, like when you've typed 1. the cursor jumps to the wrong place and you can't keep typing the // value you want. Only doing the update when the field has been validated avoids this problem. tankMessageBindingSource = new BindingSource(); tankMessageBindingSource.DataSource = tankMessage; txtDepth.DataBindings.Add("Text", tankMessageBindingSource, "Depth", false, DataSourceUpdateMode.OnValidation); txtTemperature.DataBindings.Add("Text", tankMessageBindingSource, "Temperature", false, DataSourceUpdateMode.OnValidation); txtBattery.DataBindings.Add("Text", tankMessageBindingSource, "Battery", false, DataSourceUpdateMode.OnValidation); // Bind the checkboxes to the statusMessage properties. These statements make changes to the text boxes propogate to the statusMessage object. // The binding going the other way is coded in the StatusMessage class and is only done for the PumpRunning property because that is the only // one that will be changed by control messages. // Updating the data source when the property changes is ok here because they're boolean values so there's no invalid inputs. statusMessageBindingSource = new BindingSource(); statusMessageBindingSource.DataSource = statusMessage; chkbxPumpRunning.DataBindings.Add("Checked", statusMessageBindingSource, "PumpRunning", false, DataSourceUpdateMode.OnPropertyChanged); chkbxLowLevel.DataBindings.Add("Checked", statusMessageBindingSource, "BoreLowLevel", false, DataSourceUpdateMode.OnPropertyChanged); chkbxSoftStartFail.DataBindings.Add("Checked", statusMessageBindingSource, "SoftStartFail", false, DataSourceUpdateMode.OnPropertyChanged); chkbxOverload.DataBindings.Add("Checked", statusMessageBindingSource, "PumpOverLoad", false, DataSourceUpdateMode.OnPropertyChanged); chkbxHighPressure.DataBindings.Add("Checked", statusMessageBindingSource, "HighPressure", false, DataSourceUpdateMode.OnPropertyChanged); chkbxNoFlow.DataBindings.Add("Checked", statusMessageBindingSource, "NoFlow", false, DataSourceUpdateMode.OnPropertyChanged); chkbxRestart.DataBindings.Add("Checked", statusMessageBindingSource, "ControllerRestart", false, DataSourceUpdateMode.OnPropertyChanged); commandPoller.Start(); this.AddToLog("Pump Simulator Started"); }
// Method to post a tank message to Thingsboard. public string PostToTB() { string jsonString = this.ToJSON(); ThingsboardProperties tbp = ThingsboardProperties.getInstance(); string url = $"https://{tbp.ThingsboardHost}:{tbp.ThingsboardPort}/api/v1/{tbp.LevelSensorAccessToken}/telemetry"; var content = new StringContent(jsonString, Encoding.UTF8, "application/json"); HttpResponseMessage response = Program.httpClient.PostAsync(url, content).Result; if (response.StatusCode != HttpStatusCode.OK) { Console.WriteLine(response.ToString()); System.Diagnostics.Debug.WriteLine(response.ToString()); } return(jsonString); }
private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { ThingsboardProperties.getInstance().Save(); }