/// <summary> /// Sends the base updates. /// </summary> public static void TransmitBaseUpdates() { lock (_sycnRoot) { SolarEdgeBaseData SED = DataFetcher.Instance.SolarEdgeBaseData; for (int i = _BaseUpdateCallbackChannels.Count - 1; i >= 0; i--) { if (((ICommunicationObject)_BaseUpdateCallbackChannels[i]).State != CommunicationState.Opened) { log.DebugFormat("Detected Non-Open Callback Channel for base updates: {0}", _BaseUpdateCallbackChannels[i].GetHashCode()); _BaseUpdateCallbackChannels.RemoveAt(i); continue; } try { _BaseUpdateCallbackChannels[i].TransmitBaseDataUpdate(SED); log.DebugFormat("Pushed base data update on Callback Channel: {0}", _BaseUpdateCallbackChannels[i].GetHashCode()); } catch (Exception ex) { log.Debug("Service threw exception while communicating on Callback Channel for base data updates: {0}".Build(_BaseUpdateCallbackChannels[i].GetHashCode()), ex); _BaseUpdateCallbackChannels.RemoveAt(i); } } } }
private void UpdateTimer_Elapsed(object sender, ElapsedEventArgs e) { lock (locker) { if (modbusClient != null) { updateTimer.Stop(); DateTime updateStart = DateTime.Now; bool updateSucces = false; int[] inverterResponse = null; int[] meterResponse = null;; TimeSpan inverterReadDuration = TimeSpan.MinValue; TimeSpan meterReadDuration = TimeSpan.MinValue; string ExceptionText = ""; try { if (!ConnectionEstablished) { try { ConnectToModBus(); log.Debug($"Modbus connection established for {IPAdress}:{ModBusPort}"); } catch (Exception E) { log.Debug($"A exeception occured while establishing Modbos connection to {IPAdress}:{ModBusPort}. {E.Message}", E); throw new Exception($"A exeception occured while establishing Modbos connection to {IPAdress}:{ModBusPort} {E.Message}", E); } } if (ReadInverterData) { try { DateTime StartTime = DateTime.Now; inverterResponse = modbusClient.ReadHoldingRegisters(inverterStartPos, inverterNumberOfRegisters); inverterReadDuration = DateTime.Now - StartTime; log.Debug($"Inverter data read: {inverterReadDuration.TotalMilliseconds}ms"); } catch (Exception E) { log.Debug($"Reading inverter data failed. {E.Message}", E); throw new Exception($"Reading inverter data failed. {E.Message}", E); } if (inverterResponse == null || inverterResponse.All(v => v == 0)) { log.Debug("No valid data received from inverter."); throw new Exception("No valid data received from inverter."); } } if (ReadMeterData) { try { DateTime StartTime = DateTime.Now; meterResponse = modbusClient.ReadHoldingRegisters(meterStartPos, meterNumberOfRegisters); meterReadDuration = DateTime.Now - StartTime; log.Debug($"Meter data read: {meterReadDuration.TotalMilliseconds}ms"); } catch (Exception E) { log.Debug($"Reading meter data failed. {E.Message}", E); throw new Exception($"Reading meter data failed. {E.Message}", E); } if (meterResponse == null || meterResponse.All(v => v == 0)) { log.Debug("No valid data received from inverter."); throw new Exception("No valid data received from inverter."); } } } catch (Exception E) { ExceptionText = E.Message; } if (!ExceptionText.IsNullOrWhiteSpace()) { log.Debug($"Exception occured while establishing the connection or while reading data.\n{ExceptionText}"); DisconnectFromModbus(); } else { ModbusDataUpdater U = new ModbusDataUpdater(); try { switch (DataUpdateMode) { case DataUpdateModeEnum.UpdateExistingObjects: lock (DataLocker) { if (SolarEdgeFullData == null) { SolarEdgeFullData = new SolarEdgeFullData(); } if (ReadInverterData) { U.UpdateData(inverterResponse, inverterStartPos, SolarEdgeFullData); } if (ReadMeterData) { U.UpdateData(meterResponse, meterStartPos, SolarEdgeFullData); } if (_SolarEdgeBaseData == null) { SolarEdgeBaseData = new SolarEdgeBaseData(); } if (ReadInverterData) { U.UpdateData(inverterResponse, inverterStartPos, SolarEdgeBaseData); } if (ReadMeterData) { U.UpdateData(meterResponse, meterStartPos, SolarEdgeBaseData); } }; break; case DataUpdateModeEnum.CreateNewObjects: SolarEdgeFullData FD = new SolarEdgeFullData(); if (ReadInverterData) { U.UpdateData(inverterResponse, inverterStartPos, FD); } if (ReadMeterData) { U.UpdateData(meterResponse, meterStartPos, FD); } SolarEdgeBaseData BD = new SolarEdgeBaseData(); if (ReadInverterData) { U.UpdateData(inverterResponse, inverterStartPos, BD); } if (ReadMeterData) { U.UpdateData(meterResponse, meterStartPos, BD); } lock (DataLocker) { SolarEdgeFullData = FD; SolarEdgeBaseData = BD; }; break; default: log.Error($"Unknown {nameof(DataUpdateMode)} {DataUpdateMode}"); throw new Exception($"Unknown {nameof(DataUpdateMode)} {DataUpdateMode}"); } successiveFailCount = 0; updateSucces = true; log.Debug("Data successfully updated"); } catch (Exception E) { successiveFailCount++; log.Warn($"Updating data failed. {E.Message}", E); if (successiveFailCount > maxSuccessiveFails) { DisconnectFromModbus(); log.Debug($"Disconnected from Modbus on {IPAdress}:{ModBusPort}\n{ExceptionText}. Data update failed more than {maxSuccessiveFails} times."); successiveFailCount = 0; } } } if (updateSucces) { LastDataUpdate = DateTime.Now; SolarEdgeDataIsValid = true; StartDataValidTimeoutTimer(); OnSolarEdgeDataUpdated(); } else { OnSolarEdgeDataUpdateFailed(); } int totalUpdateDurationMs = (int)(DateTime.Now - updateStart).TotalMilliseconds; int sleepDurationMs = (RefreshIntervalMs - totalUpdateDurationMs).Limit(MinIntervalBetweenUpdatesMs.Limit(10, int.MaxValue), int.MaxValue); log.Debug($"Update duration {totalUpdateDurationMs}ms. Will wait for {sleepDurationMs}ms before next update."); updateTimer.Interval = sleepDurationMs; updateTimer.Start(); } else { log.Warn($"{nameof(modbusClient)} is null. Most likely Stop has been called."); } } }