OpenEVSE supplies open-source charging station hardware and software solutions to manufacturers and individuals. OpenEVSE controllers allow manufacturers to bring their products to market sooner at a lower cost than designing from scratch. Ibeyonde is striving to IoT enable the OpneEVSE system by making OpenEVSE Charge Point OCPP compliant. Such self-service and multi-tenant devices will be required in more crowded places where there is very less density of such devices. This technology will enable smart sharing. SteVe is the server side implementation of OCPP protocol that is used to do end to end testing.
OpenEVSE comes with a standalone solution that is IP based HTTP, MQTT access to it, implemented on Huzzah hardware module. We are taking it further by make it an IoT product so that thousands of such standalone units can become part of larger multi-tenant and self-service network. The IoT module is being built on top of a raspberry pi that connects to its serial ports that speak RAPI .
OpenEvse equipment can be accessed thru its serial port. It supports Serial TTL Devices at 5v on the 6 pin header.
Serial communication with OpenEVSE
You can open a console to connect the COMM port of OpenEVSE to the USB-TTL adapter with a baud rate of 115200. From the console, you can interact with the OpenEVSE using RAPI protocol. The Remote API is very powerful for querying and controlling OpenEVSE. It is useful for information, configuration, and external applications.
Here are some interesting RAPI Get commands:
- $GG – Get real-time charging current. Returns $OK current-voltage(future hardware)
- $GP – Get real-time Temperature values from RTC chip, MCP9808, and TMP007 IR sensors. Returns $OK RTC, MCP9808, TMP007 – 0 is returned if sensor is not found.
- $GS – Set EVSE State. Returns the current state $OK State – 1 Not Connected – 2 Connected – 3 Charging – 4 Error – 5 Error.
- $GU – Get usage statistics. Returns $OK Energy used last session and lifetime
- We took a headless raspberry pi zero w with its serial ports connected to OpenEVSE.
Using PySerial we were able to talk RAPI with OpenEVSE. The PYserial module connects OpenEVSE with the client side OCPP implementation.
OpenEVSE Emulator (Python)
For any relevant testing of the OpenEVSE system, you either need a working OpenEVSE or you can use the serial port emulator. This article is mainly about implementing a serial port OpenEVSE emulator in python.
To simplify end to end testing without the need for carrying around OpenEVSE hardware we overrode the PySerial class with our custom implementation that is capable of emulating the OpenEVSE hardware. The overridden functions are: write( ), read(), close(), isOpen() and readline().
In addition, it provided the implementation of all standard OpenEVSE RAPI commands:
def get_response(self, request): request = request.decode("utf-8") .. request_for = request[0:3] .. if request_for == '$FF': response = "$OK 20" elif request_for == '$FB': response = "$OK 2" # set backlight color print("Backlight color is " + p1) lcd_color = int(p1) elif request_for == '$FD': response = "$OK 2" #disable EVSE status = _status_functions['FD'] elif request_for == '$FE': response = "$OK 2" #enable EVSE status = _status_functions['FE'] elif request_for == '$FS': ...
To emulate – connect, start charging, stop charging and disconnect it uses shared memory to pass on these actions to the emulator. This asynchronous mechanism of communication can be used by either a command line tool or a web interface.
def processSerialCommands(self, serialCmd): while True: try: cmdv = serialCmd.read() # Read command from share memory channel time.sleep(1) if cmdv is not None: if cmdv == 'Connect': print("Received start transaction on serial shm") self.update_status("$ST 2\r") # send the status update via serial channel state=2 .....
To use the emulator you need to make sure that the python picks up the emulated library instead of the PySerial.
capability = os.popen('cat ../system.properties | grep capability | cut -d"=" -f 2').read() if ("OPENEVSE_EMULATOR" in capability): import emulator_serial as serial # use emulated class if emulator mode is enabled else: import serial
*A capability file is our way of specifying what all is included on the Raspberry pi HAT.
Following code creates a serial channel to connect to OpenEVSE Emulator.
self.s = serial.Serial(port='/dev/ttyAMA0', baudrate=115200, timeout=STANDARD_SERIAL_TIMEOUT) ... while True: c = self.s.read() # read from serial port if c == b'': raise EvseTimeoutError line += c.decode('ascii') if c == b'\r': break return line
OpenEVSE and Steve
Further, the following code connects to the cloud server implementing of OCPP 1.5J based on SteVe. SteVe was developed at the RWTH Aachen University and currently implement OCPP 1.5 and 1.6. The OpenEVSE State changes (or statuses) are communicated to the OCPP 1.5J compliant cloud server. The SteVe server manages ChargePoints users, devices and charging sessions.
websocket.enableTrace(True) ws = websocket.WebSocketApp("ws://" + SIP + ":880/steve/websocket/CentralSystemService/" + uuid, on_message=on_message, on_error=on_error, on_close=on_close, header=[ "Sec-WebSocket-Protocol: ocpp1.5"]) ws.on_open = on_open ws.run_forever() ..... logging.info("created= openevse.SerialOpenEVSE()") openevse_serial = openevse.SerialOpenEVSE() while True: try: status = openevse_serial.get_status_change() if status == "not connected": logging.info("Status=%s" % status) sm.disconnect() ocpp_resp.write("Disconnect", "Success") elif status == "connected": logging.info("Status=%s" % status) if sm.isCharging(): sendRequest(ws, client_cmd.getStopTransaction(sm.getUsername(), sm.getTransactionId(), 20)) sm.stopCharging() ...