def run_outstation(self, value=None, index=0): # Callback interface for log messages self.handler = LogHandler() # Root DNP3 object used to create channels and sessions self.manager = asiodnp3.DNP3Manager(1, self.handler) # Connect via a TCPServer socket to a server self.channel_listener = ChannelListener() channel = self.manager.AddTCPServer("server", FILTERS, asiopal.ChannelRetry().Default(), LOCAL, PORT, self.channel_listener) # A composite configuration struct that contains all the config information for a dnp3 outstation stack config = asiodnp3.OutstationStackConfig(opendnp3.DatabaseSizes.AllTypes(10)) config.outstation.eventBufferConfig = opendnp3.EventBufferConfig().AllTypes(10) config.outstation.params.allowUnsolicited = True config.link.LocalAddr = 10 config.link.KeepAliveTimeout = openpal.TimeDuration().Max() # Add an outstation to a communication channel self.outstation_application = OutstationApplication() outstation = channel.AddOutstation("outstation", opendnp3.SuccessCommandHandler().Create(), self.outstation_application, config) outstation.Enable() # If the master is running, the channel listener state is OPENING assert self.channel_listener.state == opendnp3.ChannelState.OPENING if value is not None: # reset the logger id server to False before sending the cmd, if the cmd is sent successful, # the log handler should catch the logger id "server" self.handler.server = False builder = asiodnp3.UpdateBuilder() builder.Update(value, index) outstation.Apply(builder.Build()) # If the message sent successful, the log handler should catch loggerid "server" time.sleep(2) assert self.handler.server == True # Test outstation application tracking info assert self.outstation_application.link_status == opendnp3.LinkStatus.UNRESET time.sleep(1) self.manager.Shutdown()
def apply_update(self, value, index): """ Record an opendnp3 data value (Analog, Binary, etc.) in the outstation's database. The data value gets sent to the Master as a side-effect. :param value: An instance of Analog, Binary, or another opendnp3 data value. :param index: (integer) Index of the data definition in the opendnp3 database. """ _log.debug('Recording {} measurement, index={}, value={}'.format(type(value).__name__, index, value.value)) builder = asiodnp3.UpdateBuilder() builder.Update(value, index) update = builder.Build() OutstationApplication.get_outstation().Apply(update)
def apply_update(cls, value, index): """ Record an opendnp3 data value (Analog, Binary, etc.) in the outstation's database. The data value gets sent to the Master as a side-effect. :param value: An instance of Analog, Binary, or another opendnp3 data value. :param index: (integer) Index of the data definition in the opendnp3 database. """ #_log.debug('Recording DNP3 {} measurement, index={}, value={}'.format(type(value).__name__, index, value.value)) max_index = cls.get_outstation_config().get('database_sizes', 10000) if index > max_index: raise ValueError('Attempt to set a value for index {} which exceeds database size {}'.format(index, max_index)) builder = asiodnp3.UpdateBuilder() builder.Update(value, index) update = builder.Build() try: cls.get_outstation().Apply(update) except AttributeError as err: if not os.environ.get('UNITTEST', False): raise err
def test_default_constructors(self): """ Create the class object with default values for instance variable and test if the object is not empty. """ assert asiodnp3.ConsoleLogger() is not None assert asiodnp3.DefaultListenCallbacks() is not None assert asiodnp3.DefaultMasterApplication() is not None assert asiodnp3.MasterStackConfig() is not None assert asiodnp3.PrintingChannelListener is not None assert asiodnp3.PrintingSOEHandler() is not None assert asiodnp3.UpdateBuilder() is not None assert asiopal.ChannelRetry() is not None assert asiopal.ResourceManager() is not None assert asiopal.SerialSettings() is not None assert asiopal.steady_clock_t() is not None assert opendnp3.AnalogCommandEvent() is not None assert opendnp3.AnalogOutputInt16() is not None assert opendnp3.AnalogOutputInt32() is not None assert opendnp3.AnalogOutputFloat32() is not None assert opendnp3.AnalogOutputDouble64() is not None assert opendnp3.BinaryCommandEvent() is not None assert opendnp3.ClassField() is not None assert opendnp3.ControlRelayOutputBlock() is not None assert opendnp3.DNPTime() is not None assert opendnp3.Flags() is not None assert opendnp3.GroupVariationID() is not None assert opendnp3.IndexedBinary() is not None assert opendnp3.IndexedDoubleBitBinary() is not None assert opendnp3.IndexedAnalog() is not None assert opendnp3.IndexedCounter() is not None assert opendnp3.IndexedFrozenCounter() is not None assert opendnp3.IndexedBinaryOutputStatus() is not None assert opendnp3.IndexedAnalogOutputStatus() is not None assert opendnp3.IndexedOctetString() is not None assert opendnp3.IndexedTimeAndInterval() is not None assert opendnp3.IndexedBinaryCommandEvent() is not None assert opendnp3.IndexedAnalogCommandEvent() is not None assert opendnp3.IndexedSecurityStat() is not None assert opendnp3.IndexedControlRelayOutputBlock() is not None assert opendnp3.IndexedAnalogOutputInt16() is not None assert opendnp3.IndexedAnalogOutputInt32() is not None assert opendnp3.IndexedAnalogOutputFloat32() is not None assert opendnp3.IndexedAnalogOutputDouble64() is not None assert opendnp3.Binary() is not None assert opendnp3.DoubleBitBinary() is not None assert opendnp3.BinaryOutputStatus() is not None assert opendnp3.Analog() is not None assert opendnp3.Counter() is not None assert opendnp3.FrozenCounter() is not None assert opendnp3.AnalogOutputStatus() is not None assert opendnp3.TimeAndInterval() is not None assert opendnp3.OctetData() is not None assert opendnp3.OctetString() is not None assert opendnp3.SecurityStat() is not None assert opendnp3.LinkHeaderFields() is not None assert opendnp3.LinkStatistics() is not None assert opendnp3.CommandSet() is not None assert opendnp3.HeaderInfo() is not None assert opendnp3.StartStopRangeUint8() is not None assert opendnp3.StartStopRangeUint16() is not None assert opendnp3.CountUint8() is not None assert opendnp3.CountUint16() is not None assert opendnp3.HeaderUnion() is not None assert opendnp3.Header() is not None assert opendnp3.MasterParams() is not None assert opendnp3.RestartOperationResult() is not None assert opendnp3.TaskConfig() is not None assert opendnp3.ApplicationIIN() is not None assert opendnp3.DatabaseSizes() is not None assert opendnp3.EventBufferConfig() is not None assert opendnp3.OutstationConfig() is not None assert opendnp3.OutstationParams() is not None assert opendnp3.StaticTypeBitField() is not None assert opendnp3.StackStatistics() is not None assert opendnp3.IINField() is not None assert openpal.ArrayBinaryConfig() is not None assert openpal.ArrayDoubleBitBinaryConfig() is not None assert openpal.ArrayAnalogConfig() is not None assert openpal.ArrayCounterConfig() is not None assert openpal.ArrayFrozenCounterConfig() is not None assert openpal.ArrayBOStatusConfig() is not None assert openpal.ArrayAOStatusConfig() is not None assert openpal.ArrayTimeAndIntervalConfig() is not None assert openpal.ArrayBuffer() is not None assert openpal.ArrayViewBinaryConfig() is not None assert openpal.ArrayViewDoubleBitBinaryConfig() is not None assert openpal.ArrayViewAnalogConfig() is not None assert openpal.ArrayViewCounterConfig() is not None assert openpal.ArrayViewFrozenCounterConfig() is not None assert openpal.ArrayViewBOStatusConfig() is not None assert openpal.ArrayViewAOStatusConfig() is not None assert openpal.ArrayViewTimeAndIntervalConfig() is not None assert openpal.ArrayViewBuffer() is not None assert openpal.Buffer() is not None assert openpal.RingBuffer16() is not None assert openpal.RSlice() is not None assert openpal.SecureBuffer() is not None assert openpal.SettableRSlice() is not None assert openpal.SettableWSlice() is not None assert openpal.StaticBuffer4() is not None assert openpal.StaticBuffer14() is not None assert openpal.StaticBuffer100() is not None assert openpal.StaticBuffer292() is not None assert openpal.WSlice() is not None assert openpal.MonotonicTimestamp() is not None assert openpal.TimeDurationBase() is not None assert openpal.TimeDuration() is not None assert openpal.UTCTimestamp() is not None assert openpal.LogFilters() is not None assert openpal.Logger() is not None assert openpal.SerializerBinary() is not None assert openpal.SerializerDoubleBitBinary() is not None assert openpal.SerializerBinaryOutputStatus() is not None assert openpal.SerializerAnalog() is not None assert openpal.SerializerCounter() is not None assert openpal.SerializerFrozenCounter() is not None assert openpal.SerializerAnalogOutputStatus() is not None assert openpal.SerializerTimeAndInterval() is not None assert openpal.SerializerAnalogOutputInt16() is not None assert openpal.SerializerAnalogOutputInt32() is not None assert openpal.SerializerAnalogOutputFloat32() is not None assert openpal.SerializerAnalogOutputDouble64() is not None
def create_message_updates(self, simulation_id, message): """ This method creates an atomic "updates" object for any outstation to consume via their .Apply method. ---------- headers: dict A dictionary of headers that could be used to determine topic of origin and other attributes. message: object """ try: message_str = 'received message ' + str(message) builder = asiodnp3.UpdateBuilder() json_msg = yaml.safe_load(str(message)) if type(json_msg) != dict: raise ValueError(' is not a json formatted string.' + '\njson_msg = {0}'.format(json_msg)) # fncs_input_message = {"{}".format(simulation_id): {}} measurement_values = json_msg["message"]["measurements"] # Calculate each net-phase measurement if (measurement_values): myPoints = self.outstation.get_agent( ).point_definitions.all_points() netPoints = list( filter(lambda x: "net-" in x.description, myPoints)) for point in netPoints: ptMeasurements = list( filter( lambda m: m.get("measurement_mrid") in point. measurement_id, measurement_values.values())) netValue = 0.0 for m in ptMeasurements: if "VAR" in point.name: angle = math.radians(m.get("angle")) netValue = netValue + math.sin(angle) * float( m.get("magnitude")) elif "Watts" in point.name: angle = math.radians(m.get("angle")) netValue += math.cos(angle) * float( m.get("magnitude")) else: netValue += float(m.get("magnitude")) point.magnitude = netValue builder.Update(opendnp3.Analog(point.magnitude), point.index) # Calculate each measurement for y in measurement_values: # print(self.processor_point_def.points_by_mrid()) m = measurement_values[y] if "magnitude" in m.keys(): for point in self.outstation.get_agent( ).point_definitions.all_points(): #print("point",point.name) #print("y",y) if m.get("measurement_mrid") == point.measurement_id: if point.magnitude != float(m.get("magnitude")): point.magnitude = float(m.get("magnitude")) builder.Update( opendnp3.Analog(point.magnitude), point.index) if point.measurement_type == "VA": if "VAR" in point.name: angle = math.radians(m.get("angle")) point.magnitude = math.sin(angle) * float( m.get("magnitude")) builder.Update( opendnp3.Analog(point.magnitude), point.index) if "Watts" in point.name: angle1 = math.radians(m.get("angle")) point.magnitude = math.cos(angle1) * float( m.get("magnitude")) builder.Update( opendnp3.Analog(point.magnitude), point.index) if "angle" in point.name: angle2 = math.radians(m.get("angle")) builder.Update(opendnp3.Analog(angle2), point.index) elif "value" in m.keys(): for point in self.outstation.get_agent( ).point_definitions.all_points(): if m.get( "measurement_mrid" ) == point.measurement_id and point.value != m.get( "value"): point.value = m.get("value") builder.Update(opendnp3.Binary(point.value), point.index) # Return the atomic "updates" object print("Updates Created") return builder.Build() except Exception as e: message_str = "An error occurred while trying to translate the message received" + str( e)