Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New asdus and asdu design #9

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 29 additions & 17 deletions examples/ip_cliente.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,37 @@
import reeprotocol.protocol
import datetime


def run_example(ip, port, der, dir_pm, clave_pm):
physical_layer = reeprotocol.ip.Ip((ip, port))
link_layer = reeprotocol.protocol.LinkLayer(der, dir_pm)
link_layer.initialize(physical_layer)
app_layer = reeprotocol.protocol.AppLayer()
app_layer.initialize(link_layer)
try:
physical_layer = reeprotocol.ip.Ip((ip, port))
link_layer = reeprotocol.protocol.LinkLayer(der, dir_pm)
link_layer.initialize(physical_layer)
app_layer = reeprotocol.protocol.AppLayer()
app_layer.initialize(link_layer)

physical_layer.connect()
link_layer.link_state_request()
link_layer.remote_link_reposition()
logging.info("before authentication")
resp = app_layer.authenticate(clave_pm)
logging.info("CLIENTE authenticate response {}".format(resp))
logging.info("before read")
"""
for resp in app_layer\
.read_integrated_totals(datetime.datetime(2017, 10, 1, 1, 0),
datetime.datetime(2017, 11, 1, 0, 0)):
logging.info("read response {}".format(resp))
"""
for resp in app_layer.get_info():
logging.info("read response {}".format(resp))
except Exception:
raise
finally:
#app_layer.finish_session()
physical_layer.disconnect()
sys.exit(1)

physical_layer.connect()
link_layer.link_state_request()
link_layer.remote_link_reposition()
logging.info("before authentication")
resp = app_layer.authenticate(clave_pm)
logging.info("CLIENTE authenticate response {}".format(resp))
logging.info("before read")
for resp in app_layer\
.read_integrated_totals(datetime.datetime(2017, 10, 1, 1, 0),
datetime.datetime(2017, 11, 1, 0, 0)):
logging.info("read response {}".format(resp))
physical_layer.disconnect()

if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
Expand Down
159 changes: 117 additions & 42 deletions reeprotocol/app_asdu.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@
import datetime


__all__ = [
'C_AC_NA_2',
'C_CI_NU_2',
'C_FS_NA_2',
'C_TI_NA_2',
'C_RD_NA_2',
'M_IT_TK_2', # M type are responses no need to be listed
'M_TI_TA_2', # M type are responses no need to be listed
'P_MP_NA_2',
]


class AppAsduRegistry(type):
types = dict()

Expand All @@ -19,56 +31,132 @@ def register_class(cls):


class BaseAppAsdu(metaclass=AppAsduRegistry):
pass

data_length = 0

@property
def length(self):
return self.data_length + 0x09

@property
def values(self):
return "\n".join([
" {}: {}".format(k, v) for k,v in vars(self).items()
])

def __repr__(self):
return '\n'.join([
" -- {class_name} Begin --",
"{values}",
" -- {class_name} End --"
]).format(
class_name=self.__class__.__name__,
values=self.values
)


class C_TI_NA_2(BaseAppAsdu):
"""
Leer fecha y hora actuales
"""
type = 103
causa_tm = 5

def to_bytes(self):
return bytes()

def from_hex(self, data, cualificador_ev):
pass


class M_TI_TA_2(BaseAppAsdu):
"""
Fecha y hora actuales
"""
type = 72
causa_tm = 5

def __init__(self):
self.tiempo = None

def from_hex(self, data, cualificador_ev):
self.tiempo = TimeA()
self.tiempo.from_hex(data)


class C_RD_NA_2(BaseAppAsdu):
"""
Leer identificador de fabricante y equipo
"""
type = 100
causa_tm = 5

def to_bytes(self):
return bytes()

def from_hex(self, data, cualificador_ev):
pass


class P_MP_NA_2(BaseAppAsdu):
"""
Identificador del fabricante y equipo
"""
type = 71
data_length = 0x06

def __init__(self):
self.codigo_fabricante = None
self.codigo_equipo = None

def to_bytes(self):
return bytes()

def from_hex(self, data, cualificador_ev):
self.codigo_fabricante = struct.unpack("B", data[1:2])[0]
self.codigo_equipo = struct.unpack("I", data[2:6])[0]


class C_AC_NA_2(BaseAppAsdu):
"""
used to send the password of the thing
"""
type = 183
data_length = 0x04

def __init__(self, clave=0):
self.clave = clave

def from_hex(self, data, cualificador_ev):
self.clave = struct.unpack("I", data)[0]

@property
def length(self):
return 0x0d

def to_bytes(self):
return struct.pack("I", self.clave)

def __repr__(self):
output = " -- C_AC_NA_2 Begin -- \n"
output += " clave: " + str(self.clave) + "\n"
output += " -- C_AC_NA_2 End \n"
return output


class C_FS_NA_2(BaseAppAsdu):
"""
Finalizar sesión
"""

type = 187

def from_hex(self, data, cualificador_ev):
pass

@property
def length(self):
return 0x09

def to_bytes(self):
return bytes()

def __repr__(self):
output = " -- C_FS_NA_2 Begin -- \n"
output += " -- C_FS_NA_2 End \n"
return output


class C_CI_NU_2(BaseAppAsdu):
"""
Leer totales integrados operacionales repuestos periódicamente por intervalo
de tiempo y rango de direcciones
"""

type = 123
data_length = 0x06
causa_tm = 6

def __init__(self, start_date=datetime.datetime.now(),
end_date=datetime.datetime.now()):
Expand All @@ -83,10 +171,6 @@ def from_hex(self, data, cualificador_ev):
self.tiempo_inicial.from_hex(data[2:7])
self.tiempo_final.from_hex(data[7:12])

@property
def length(self):
return 0x15

def to_bytes(self):
response = bytearray()
response.extend(struct.pack("B", self.primer_integrado))
Expand All @@ -95,23 +179,22 @@ def to_bytes(self):
response.extend(self.tiempo_final.to_bytes())
return response

def __repr__(self):
output = " -- C_CI_NU_2 Begin -- \n"
output += " primer_integrado: " + str(self.primer_integrado) + "\n"
output += " ultimo_integrado: " + str(self.ultimo_integrado) + "\n"
output += " tiempo_inicial: " + str(self.tiempo_inicial) + "\n"
output += " tiempo_final: " + str(self.tiempo_final) + "\n"
output += " -- C_CI_NU_2 End \n"
return output
@property
def length(self):
return 0x15


class M_IT_TK_2(BaseAppAsdu):
"""
Totales integrados operacionales repuestos periódicamente, 4 octetos
(incrementos de energía, en kWh o kVARh)
"""

type = 11

def __init__(self):
self.valores = []
self.tiempo = None
pass

def from_hex(self, data, cualificador_ev):
for i in range(0, cualificador_ev):
Expand All @@ -129,14 +212,6 @@ def from_hex(self, data, cualificador_ev):
self.tiempo = TimeA()
self.tiempo.from_hex(data[position:position+5])

def __repr__(self):
output = " -- M_IT_TK_2 Begin -- \n"
output += (" contadores (direccion objeto, total integrado"
", cualificador) " + str(self.valores) + "\n")
output += " tiempo: " + str(self.tiempo) + "\n"
output += " -- M_IT_TK_2 End \n"
return output


class TimeA():

Expand Down Expand Up @@ -237,4 +312,4 @@ def __repr__(self):
+ (":".join("%02x" % b for b in self.to_bytes())) + "\n")
output += " datetime: " + str(self.datetime) + "\n"
output += " -- TiempoA End \n"
return output
return str(self.datetime)
2 changes: 1 addition & 1 deletion reeprotocol/base_asdu.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def __repr__(self):
output += " direccion punto medida: " + str(self.dir_pm) + "\n"
output += " direccion registro: " + str(self.dir_registro) + "\n"
output += " CONTENIDO: " + (":".join("%02x" % b for b in self.data)) + "\n"
output += str(self.content)
output += str(self.content) + "\n"
output += " checksum: " + str(self.checksum) + " " +hex(self.checksum) + "\n"
output += " " + (":".join("%02x" % b for b in self.buffer)) + "\n"
output += "----- VariableAsdu End -----"
Expand Down
Loading