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

SMC JXC91 write #94

Open
JuhaBackman opened this issue Jan 20, 2021 · 5 comments
Open

SMC JXC91 write #94

JuhaBackman opened this issue Jan 20, 2021 · 5 comments

Comments

@JuhaBackman
Copy link

JuhaBackman commented Jan 20, 2021

Hi

I have succesfully read information from JXC91, but write doesn't work.
Could anyone interpret the log file what is wrong?

from cpppo.server.enip import poll
from cpppo.server.enip.get_attribute import proxy_simple as device

[...]
Reading:

    self.poller = threading.Thread(
        target=poll.poll, kwargs={ 
            'proxy_class':	device,
            'address': 	(self.hostname, 44818),
            'cycle':	0.1,
            'timeout':	0.05,
            'process':	lambda par,val: self.update(val),
            'params':	[('@0x4/0x64/0x03',('USINT','USINT','WORD','DINT','UINT','UINT','DINT','USINT','USINT','USINT','USINT','WORD','WORD','DWORD','DWORD','DWORD'))],
        })
    self.poller.daemon			= True
    self.poller.start()

Writing:

    values = "512,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"
    val, = device( self.hostname ).write( [('@0x4/0x96/0x03 = ' + values)])

The result is "None"

Log file:

01-20 10:41:52.317 MainThread enip.get DETAIL is_request Validating request: '@0x4/0x96/0x03 = 512,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0'
01-20 10:41:52.317 MainThread enip.cli DETAIL parse_oper Tag: '@0x4/0x96/0x03' yields Operation: {'method': 'write', 'path': [{'class': 4}, {'instance': 150}, {'attribute': 3}], 'tag_type': 195, 'data': [512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'elements': 17}.update({'route_path': False, 'send_path': '', 'priority_time_tick': None, 'timeout_ticks': None})
01-20 10:41:52.317 MainThread enip.get DETAIL opp__att_t Parsed attribute '@0x4/0x96/0x03 = 512,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0' (type None) into operation: {'method': 'write', 'path': [{'class': 4}, {'instance': 150}, {'attribute': 3}], 'tag_type': 195, 'data': [512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'elements': 17, 'route_path': False, 'send_path': '', 'priority_time_tick': None, 'timeout_ticks': None}
01-20 10:41:52.317 MainThread enip.cli DETAIL cip_send Client CIP Send: {
'enip.session_handle': 2089025553,
'enip.options': 0,
'enip.status': 0,
'enip.sender_context.input': bytearray(hexload(r'''
00000000: 30 00 00 00 00 00 00 00 |0.......|
''')),
'enip.CIP.send_data.interface': 0,
'enip.CIP.send_data.timeout': 8,
'enip.CIP.send_data.CPF.item[0].type_id': 0,
'enip.CIP.send_data.CPF.item[1].type_id': 178,
'enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[0].class': 4,
'enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[1].instance': 150,
'enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[2].attribute': 3,
'enip.CIP.send_data.CPF.item[1].unconnected_send.request.write_tag.elements': 17,
'enip.CIP.send_data.CPF.item[1].unconnected_send.request.write_tag.data': list(
512, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
),
'enip.CIP.send_data.CPF.item[1].unconnected_send.request.write_tag.type': 195,
'enip.CIP.send_data.CPF.item[1].unconnected_send.request.service': 77,
'enip.CIP.send_data.CPF.item[1].unconnected_send.request.input': bytearray(hexload(r'''
00000000: 4d 03 20 04 24 96 30 03 c3 00 11 00 00 02 00 00 |M. .$.0.........|
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |..............|
''')),
}
01-20 10:41:52.317 MainThread enip.cli DEBUG cip_send EtherNet/IP: 24 + CIP: 62 == 86 bytes total
01-20 10:41:52.323 MainThread enip.cli INFO send EtherNet/IP--> 192.168.1.101:44818 send 86: b'o\x00>\x00\x11\x00\x84|\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x02\x00\x00\x00\x00\x00\xb2\x00.\x00M\x03 \x04$\x960\x03\xc3\x00\x11\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
01-20 10:41:52.323 MainThread enip.cli DETAIL format_pat Formatted @0x0004/150/3 from: [{'class': 4}, {'instance': 150}, {'attribute': 3}]
01-20 10:41:52.323 MainThread enip.cli DETAIL issue Sent 0.006/ 5.000s: Single Write Tag @0x0004/150/3 {
'path.segment[0].class': 4,
'path.segment[1].instance': 150,
'path.segment[2].attribute': 3,
'write_tag.elements': 17,
'write_tag.data': list(
512, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
),
'write_tag.type': 195,
'service': 77,
'input': bytearray(hexload(r'''
00000000: 4d 03 20 04 24 96 30 03 c3 00 11 00 00 02 00 00 |M. .$.0.........|
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |..............|
''')),
}
01-20 10:41:52.323 MainThread enip.cli DETAIL issue Sending 1 (Context b'0')
01-20 10:41:52.323 MainThread enip.cli DETAIL pipeline Issuing 0/ 1; curr: 0 - last: -1 == 1 depth vs. max 2
01-20 10:41:52.324 MainThread enip.cli INFO next EtherNet/IP<-- 192.168.1.101:44818 rcvd 44: b'o\x00\x14\x00\x11\x00\x84|\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\xb2\x00\x04\x00\xcd\x00\x08\x00'
01-20 10:41:52.324 MainThread cpppo DEBUG reset ((enip.((payload.((byte))) -- reset
01-20 10:41:52.324 MainThread cpppo DEBUG reset ( header.( command.((byte)) -- reset
01-20 10:41:52.324 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.command = 111 (format '<H' over array('B', [111, 0]))
01-20 10:41:52.324 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.length = 20 (format '<H' over array('B', [20, 0]))
01-20 10:41:52.324 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.session_handle = 2089025553 (format '<I' over array('B', [17, 0, 132, 124]))
01-20 10:41:52.324 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.status = 0 (format '<I' over array('B', [0, 0, 0, 0]))
01-20 10:41:52.324 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.options = 0 (format '<I' over array('B', [0, 0, 0, 0]))
01-20 10:41:52.325 MainThread cpppo DEBUG delegate ( payload.((byte)) -- repeat='enip.length' == 20

@pjkundert
Copy link
Owner

You probably want to write 36 bytes of raw SINT data using Set Attribute Single, not C*Logix Write Tag.

Something along the lines of this should write the 36(?) bytes of data to the attribute using Set Attribute Single:

from cpppo.server.enip.get_attribute import attribute_operations
values = '(SINT)' + ','.join( ['0'] * 36 )
val, = device( self.hostname ).write( attribute_operations( [('@0x4/0x96/0x03 = ' + values)] ))

@JuhaBackman
Copy link
Author

Than you for your answer.
Unofortunately that didn't help.

Actually what I want to write is this based on the the EDS file:

Assmbly:

  • Assem150
    • Path: 20 04 24 96 30 03
    • Class: 4
    • Instance: 150
    • Attribute 3
    • Members: 16

Param300 - STEP NUMBER CHOICE (size 8 bits)
Param301 - CONTROL FLAGS (8)
Param302 - ACT FLAGS (16)
Param303 - EXECUTION FLAG (8)
Param304 - OP METHOD (8)
Param305 - SPEED (16)
Param306 - TARGET POSITION (32)
Param307 - ACCELATION (16)
Param308 - DEACCELATION (16)
Param309 - PUSHUING FORCE (16)
Param310 - THRESHOLD (16)
Param311 - PUSHING SPEED (16)
Param312 - POSITIONING FORCE (16)
Param313 - AREA POINT 1 (32)
Param314 - AREA POINT 2 (32)
Param315 - FIXED WIDTH (32)

However, the Operation Manuals uses 17 "WORD" type values (totally 34 bytes).
I tried based on your advise:

values = "512,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"
val, = device( self.hostname ).write( attribute_operations( [('@0x4/0x96/0x03 = (dint)' + values)] ))

That should put the motor controller on. But I get:

File "/home/luke/.local/lib/python3.8/site-packages/cpppo/server/enip/get_attribute.py", line 536, in opp__att_typ_uni
assert self.is_request( a ),
AssertionError: Not a valid read/write target: {'method': 'set_attribute_single', 'path': [{'class': 4}, {'instance': 150}, {'attribute': 3}], 'tag_type': 196, 'data': [512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'elements': 17}

What should I do now?

@pjkundert
Copy link
Owner

I've pushed version 4.4.2, which allows you to specify a specific operations_parser for the proxy:

#
# Basic CIP I/O Test
#
# Target Simulator:
#     python3 -m cpppo.server.enip -S -vv SCADA@0x4/0x96/3=INT[18
#
import cpppo
from cpppo.server.enip.get_attribute import (
    attribute_operations, proxy_simple as device )
from cpppo.server.enip import client

import logging
cpppo.log_cfg['level'] = logging.DEBUG
logging.basicConfig( **cpppo.log_cfg )

hostname = 'localhost'

# Our target CIP Attribute contains a 36 bytes == 18 x INT value
attribute = '@0x4/0x96/3'
values = "512,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"
operations = [attribute + ' = (INT)' + values]
print( "Raw operations: %r" % operations )

operations_parser = attribute_operations
operations_out = list( operations_parser( operations ))

assert operations_out == [{
    'method': 'set_attribute_single',
    'path': [{'class': 4}, {'instance': 150}, {'attribute': 3}],
    'tag_type': 195,
    'data': [512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    'elements': 18
}]

# Force basic CIP Get/Set Attribute I/O operations
via = device( hostname, operations_parser=operations_parser )
val, = via.write( operations )

This should allow you to force basic CIP Get/Set Attribute I/O requests while using "typed" data (eg. INT), instead of defaulting to using C*Logix I/O for typed data.

@JuhaBackman
Copy link
Author

Thank you for you help.

The code itself work, but still I got result "None" and the controller does nothing...

@ikerlobop
Copy link

The program to activate a group of SMC solenoid valves has worked for me by adapting the data provided by the EDS file.

To achieve this, I modified the Values, Data, and adjusted the number of elements, based on the response you just provided here, and the program works perfectly.

Thank you very much @pjkundert

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants