-
Notifications
You must be signed in to change notification settings - Fork 120
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add the package which you have written as well. Without the package, nobody can try out this code.
Also, cpppo library needs to be added to requirements.txt
@@ -0,0 +1,95 @@ | |||
# -*- coding: utf-8 -*- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use Pep 8 convention for naming the module. https://www.python.org/dev/peps/pep-0008/#package-and-module-names
Not only for this module and class, but for all of your code.
log = logging.getLogger(__name__) | ||
|
||
|
||
class EtherNetDeviceComms(DeviceComms): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be CipEtherentDeviceComms. Ethernet is a generic protocol.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EtherNet/IP (EtherNet Industrial Protocol) means CIP implemented over ethernet.
So I changed the class name to EtherNetIPDeviceComms which I thought would be more suitable.
Or should I make it CipEtherentDeviceComms?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://en.wikipedia.org/wiki/EtherNet/IP is a specific implementation of CIP. I think we should call this: CipEtherNetIpDeviceComms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay
import logging | ||
|
||
from liota.device_comms.device_comms import DeviceComms | ||
from liota.lib.transports.ENIP import EtherNetIP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename ENIP
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed as EtherNetIP
|
||
|
||
if host is None: | ||
log.error("Host can't be none") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove log statement. Once you raise an exception, it will automatically get logged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the log statement.
data = self.client.read() | ||
return data | ||
|
||
def send(self, message): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we implement send() and receive()? Whatever functionality you have in write() has to be part of send() and read() has to be part of receive()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made these changes. Now, Send() contains write() and receive () contains read().
liota/lib/transports/ENIP.py
Outdated
assert self.conn.readable( timeout=1.0 ), "Failed to receive reply" | ||
rpy = next( self.conn ) | ||
data = rpy['enip']['CIP']['send_data']['CPF']['item'][1]['unconnected_send']['request']['read_frag']['data'][0] | ||
print(data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove print, log if necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed all print statements
liota/lib/transports/ENIP.py
Outdated
req = self.conn.read("Scada[0]") | ||
assert self.conn.readable( timeout=1.0 ), "Failed to receive reply" | ||
rpy = next( self.conn ) | ||
data = rpy['enip']['CIP']['send_data']['CPF']['item'][1]['unconnected_send']['request']['read_frag']['data'][0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where are these magic strings coming from? Is it always the same? What if one of them is None?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to fetch the data from the response got from the server, which is in json format.
It is the same always.
liota/lib/transports/ENIP.py
Outdated
|
||
|
||
def shutdown( self ): | ||
if not self.udp: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if it is not UDP?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not able to figure this out, could you please take a look at this - https://github.com/pjkundert/cpppo/blob/master/server/enip/client.py#L401
DeviceComms for EtherNetIP protocol | ||
""" | ||
|
||
def __init__(self, host=None, port=None, timeout=None, dialect=None, profiler=None, udp=False, broadcast=False, source_address=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the default value of host None, if we are immediately checking for it to be not none?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made the localhost as default, if host is empty, as mentioned in https://github.com/pjkundert/cpppo/blob/master/server/enip/client.py#L300
def __init__(self, host=None, port=None, timeout=None, dialect=None, profiler=None, udp=False, broadcast=False, source_address=None): | ||
|
||
self.host = host | ||
self.port = port |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens when port is none? where does it connect?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When port is None, I think the default port will be used. I want you to check this once - https://github.com/pjkundert/cpppo/blob/master/server/enip/client.py#L326
Also, it is mentioned if default port is not used, use 44818 - https://github.com/pjkundert/cpppo/blob/master/server/enip/client.py#L302
As of now I have changed the port as 44818 in the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok. Thanks for checking it out. If the underlying library accepts None, then yes we should accept None. Let us not hard-code it to 44818, as it is a non-standard port, and if library implementation changes the port, we will get an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
@@ -0,0 +1,95 @@ | |||
# -*- coding: utf-8 -*- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a README file with instructions how to use this protocol.
@@ -0,0 +1,91 @@ | |||
# -*- coding: utf-8 -*- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a simulation. Let us name it as CipSocketGraphite.py to indicate it is have Cip as DeviceComms, Socket as DCCComms and Graphite as DCC.
Also add the writer code as "simulator", so that someone can test this package. In Readme, also add the complete steps of how to run the simulator and load this package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay
|
||
|
||
|
||
def clean_up(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
disconnect the DeviceComms as well after stopping the metric collection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay
self.config = read_user_config(config_path + '/sampleProp.conf') | ||
|
||
|
||
ethernetIP_conn = CipEtherNetIpDeviceComms(host=self.config['EtherNetIP'],port=None,timeout=None, dialect=None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
None values need not be specified here. So remove them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, will remove them
|
||
|
||
def _connect(self): | ||
self.client = EtherNetIP(self.host,self.port,self.timeout,self.dialect,self.profiler,self.udp,self.broadcast,self.source_address) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Run autopep8 to correct the formatting.
@@ -0,0 +1,28 @@ | |||
import time |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright missing.
tag_type=tag_type) | ||
|
||
except AssertionError: | ||
print "Response timed out!! Tearing Connection and Reconnecting!!!!!" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you actually reconnecting anywhere??
elements = len (data) | ||
tag_type = client.enip.DINT.tag_type | ||
tag = "Scada" | ||
req = conn.write( tag, elements=elements, data=data, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
formatting? use autopep8
import logging | ||
|
||
from liota.device_comms.device_comms import DeviceComms | ||
from liota.lib.transports.EtherNetIP import EtherNetIP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename EtherNetIP to CipEtherNetIp
if data is None: | ||
raise TypeError("Data can't be none") | ||
else: | ||
self.client.send(tag,elements,data,tagType) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
formatting.
@@ -49,3 +49,6 @@ LivingRoomTemperatureTopic = "home/living-room/temperature" | |||
LivingRoomHumidityTopic = "home/living-room/humidity" | |||
LivingRoomLightTopic = "home/living-room/light" | |||
|
|||
#### [EtherNet/IP] #### | |||
EtherNetIP = "EtherNet/IP IP" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename to CipEtherNetIp
@@ -49,3 +49,6 @@ LivingRoomTemperatureTopic = "home/living-room/temperature" | |||
LivingRoomHumidityTopic = "home/living-room/humidity" | |||
LivingRoomLightTopic = "home/living-room/light" | |||
|
|||
#### [EtherNet/IP] #### |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Provide better comment like CIP Etherent/IP Device Comms parameters
Closing this pull request, as this was incorrectly created and a new one (#187) is raised. |
Added EtherNetIP protocol support for liota, which uses cpppo library internally.