Unable to gRPC remotely with Python
I have configured my controller AXCF 3152 (2022.6) for remote gRPC and confirmed this works via Output.log and grpcurl.
With Python I get errors. I am unable to figure out why this is.
Any pointers?
warnings.warn(
<Response [200]>
Traceback (most recent call last):
File ".\plcnext.py", line 41, in <module>
stub.ReadSingle(request)
File "D:\...\grpc\PLCnext\python\.venv\lib\site-packages\grpc\_channel.py", line 1161, in __call__
return _end_unary_response_blocking(state, call, False, None)
File "D:\...\grpc\PLCnext\python\.venv\lib\site-packages\grpc\_channel.py", line 1004, in _end_unary_response_blocking
raise _InactiveRpcError(state) # pytype: disable=not-instantiable
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
status = StatusCode.UNAVAILABLE
details = "failed to connect to all addresses; last error: UNAVAILABLE: ipv4:192.168.2.2:50051: End of TCP stream"
debug_error_string = "UNKNOWN:failed to connect to all addresses; last error: UNAVAILABLE: ipv4:192.168.2.2:50051: End of TCP stream {grpc_status:14, created_time:"2023-09-25T10:07:25.1373492+00:00"}"
Pipenv:
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
grpcio = "*"
grpcio-tools = "*"
requests = "*"
[dev-packages]
[requires]
python_version = "3.8"
Imports in .py:
import requests
import grpc
# Import the PLCnext gRPC service's protocol definition file.
import Plc.Gds.ISubscriptionService_pb2_grpc as SubStub
import Plc.Gds.ISubscriptionService_pb2 as Sub
import Plc.Gds.SubscriptionKind_pb2 as SubKind
import Plc.Gds.IDataAccessService_pb2_grpc as DAStub
import Plc.Gds.IDataAccessService_pb2 as DA
Actual code:
channel = grpc.insecure_channel('192.168.2.2:50051')
stub = DAStub.IDataAccessServiceStub(channel)
request = DA.IDataAccessServiceReadSingleRequest()
request.portName = 'Arp.Plc.Eclr/MainInstance.MY_INT'
stub.ReadSingle(request)
print(response)
channel.close()
Comments
Thanks, it was resolved with a little help from Phoenix Contact.
The insecure_channel was not enough to establish a connection with the server. I needed a secure_channel with a self-signed certificate.
with open("server.crt", "rb") as f:
ca_cert = f.read()
channel = grpc.secure_channel('10.0.21.111:50051', grpc.ssl_channel_credentials(ca_cert))
To acquire a certificate, the steps are described here:
https://www.plcnext-community.net/makersblog/secure-remote-grpc-using-grpcurl/