mobilityhouse / ocpp

Python implementation of the Open Charge Point Protocol (OCPP).
MIT License
788 stars 310 forks source link

> Hi, for a couple of days im trying to implement RemoteStartTransaction. I tried to look for examples of how central system sending request on charge point but didn't find anything, so i tried myself and here what i got #158

Closed Aashutosh3804 closed 3 years ago

Aashutosh3804 commented 3 years ago

Hi, for a couple of days im trying to implement RemoteStartTransaction. I tried to look for examples of how central system sending request on charge point but didn't find anything, so i tried myself and here what i got

central_system.py:

import asyncio
from datetime import datetime
#from simple_charge.config.settings import *
#from simple_charge.config.handlers import *
from pymongo import MongoClient
from bson import ObjectId
import json
from ocpp.routing import on
from ocpp.v16 import ChargePoint as cp
from ocpp.v16.enums import *
from ocpp.v16 import call_result, call

try:
    import websockets
except ModuleNotFoundError:
    print("This example relies on the 'websockets' package.")
    print("Please install it by running: ")
    print()
    print(" $ pip install websockets")
    import sys
    sys.exit(1)

class ChargePoint(cp):
    @on(Action.BootNotification)
    def on_boot_notification(self, charge_point_vendor, charge_point_model, **kwargs):
        return call_result.BootNotificationPayload(
            current_time=datetime.utcnow().isoformat(),
            interval=10,
            status=RegistrationStatus.accepted
        )

    @on(Action.Heartbeat)
    def on_heartbeat(self):
        return call_result.HeartbeatPayload(
            current_time=datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S') + "Z"
        )

    @on(Action.Authorize)
    def on_authorize(self, id_tag):
        return call_result.AuthorizePayload(
            id_tag_info={
                "status": 'Accepted'
            }
        )

    @on(Action.StartTransaction)
    def on_start_transaction(self, connector_id, id_tag, timestamp, meter_start, reservation_id):
        return call_result.StartTransactionPayload(
            id_tag_info={
                "status": 'Accepted'
            },
            transaction_id=int(1)
        )

    @on(Action.StopTransaction)
    def on_stop_transaction(self, transaction_id, id_tag, timestamp, meter_stop):
        return call_result.StopTransactionPayload()

    @on(Action.MeterValues)
    def on_meter_value(self):
        return call_result.MeterValuesPayload()

    @on(Action.StatusNotification)
    def on_status_notification(self, connector_id, error_code, status):
        return call_result.StatusNotificationPayload()

    @on(Action.DataTransfer)
    def on_data_transfer(self, vendor_id, message_id, data):
        return call_result.DataTransferPayload(
            status='Accepted'
        )

    async def remote_start_transaction(self):
        request = call.RemoteStartTransactionPayload(
            id_tag='1'
        )
        response = await self.call(request)
        if response.status == RemoteStartStopStatus.accepted:
            print("Transaction Started!!!")

    async def remote_stop_transaction(self):
        request = call.RemoteStopTransactionPayload(
            transaction_id=1
        )
        response = await self.call(request)

        if response.status == RemoteStartStopStatus.accepted:
            print("Stopping transaction")

connected = set()
clients = dict()
ping_counter = 0
clients_couter = 0

@asyncio.coroutine
async def on_connect(websocket, path):
    charge_point_id = path.strip('/')
    cp = ChargePoint(charge_point_id, websocket)
    try:
        await asyncio.gather(cp.start(), register(websocket, path))
    except websockets.exceptions.ConnectionClosed:
        connected.remove(websocket)
        print("Charge Point disconnected")

@asyncio.coroutine
async def actions(websocket, path):
    charge_point_id = path.strip('/')
    cp = ChargePoint(charge_point_id, websocket)
    if websocket:
        print("B action", websocket)
        await cp.remote_start_transaction()

@asyncio.coroutine
async def register(websocket, path):
    await asyncio.sleep(2)
    connected.add(websocket)
    await actions(websocket, path)

charge_point.py:

import asyncio
from datetime import datetime
from protocols.central_system import actions, on_connect

try:
    import websockets
except ModuleNotFoundError:
    print("This example relies on the 'websockets' package.")
    print("Please install it by running: ")
    print()
    print(" $ pip install websockets")
    import sys
    sys.exit(1)

from ocpp.v16 import call, call_result
from ocpp.v16 import ChargePoint as cp
from ocpp.v16.enums import *
from ocpp.routing import on, after

class ChargePoint(cp):
    async def send_boot_notification(self):
        request = call.BootNotificationPayload(
            charge_point_model="Optimus",
            charge_point_vendor="The Mobility House"
        )
        response = await self.call(request)
        if response.status == RegistrationStatus.accepted:
            print("Connected to central system.")

    @on(Action.RemoteStartTransaction)
    def remote_start_transaction(self, id_tag):
        return call_result.RemoteStartTransactionPayload(status=RemoteStartStopStatus.accepted)

    @on(Action.RemoteStopTransaction)
    def remote_stop_transaction(self, transaction_id):
        return call_result.RemoteStopTransactionPayload(status=RemoteStartStopStatus.accepted)

async def main():
    async with websockets.connect(
        'ws://localhost:9000/CP_1',
            subprotocols=['ocpp1.6']
    ) as ws:

        cp = ChargePoint('CP_1', ws)
        await asyncio.gather(cp.start(), cp.send_boot_notification())

if __name__ == '__main__':
    try:
        # asyncio.run() is used when running this example with Python 3.7 and
        # higher.
        asyncio.run(main())
    except AttributeError:
        # For Python 3.6 a bit more code is required to run the main() task on
        # an event loop.
        loop = asyncio.get_event_loop()
        loop.run_until_complete(main())
        loop.close()

run.py:

from protocols.central_system import actions, on_connect, connected
import websockets
import asyncio

async def main():
    server = await websockets.serve(
        on_connect,
        '0.0.0.0',
        9000,
        subprotocols=['ocpp1.6']
    )

    await server.wait_closed()

if __name__ == '__main__':
    #loop = asyncio.get_event_loop()
    #asyncio.ensure_future(main())
    #asyncio.ensure_future(actions())
    #loop.run_until_complete(main())
    #loop.run_forever()

    try:
        # asyncio.run() is used when running this example with Python 3.7 and
        # higher.
        asyncio.run(main())
    except AttributeError:
        # For Python 3.6 a bit more code is required to run the main() task on
        # an event loop.
        loop = asyncio.get_event_loop()
        loop.run_until_complete(main())
        loop.close()

Basicly im able to send from central system id_tag to charge point, but it seems charge point sending his response somewhere else, becouse im getting TimeoutErrore on central system side. Can you please help? Or provide an example of how central system sending requests to charge point?

Can You please tell how you are to triggering RemoStartTransaction from centralSystem programitically For each heartbeat request i want to trigger RemoteStartTransaction on certain condition But i am able to send the request but the I got asyncio timeout and not able to get response

Originally posted by @Aashutosh3804 in https://github.com/mobilityhouse/ocpp/issues/81#issuecomment-734797973

analge-hk commented 3 years ago

I hope you might have resolved the issue already if not try to send the request after you receive boot notification.

vinothkrstatiq commented 2 years ago

getting error in central system while compiling DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead async def on_connect(websocket, path):

dhwanishah1 commented 6 months ago

hi, may I know when remote_stop_transaction will be run in this code? My code can do start remote transaction but I noticed it does not call remote_start_transaction.