Power API responding randomly

In 50% of the case, when I try :
api.get_battery_level()
get_firmware_ver()
get_system_current()

I do not get response or CRC error.
With api.get_rtc_time(Definition.TIME_FORMAT_EPOCH) it is nearly a no or bad response in 80% case.

I tried also with a 1000ms timeout (instead of 10)… same result.

Do you have an idea ?

I have intermittent trouble unless I shutdown the agent and request service.

sudo systemctl stop power_agent.service
sudo systemctl stop power_request.service

it’s probably due to response times and commands sent on a short interval on the i2c bus. (and if the power_* services are running, you can have background conflicting commands)

also, did you increase the I2C bus frequency? some modules may not like that. for example, the RPI Sense hat works fine at 100 and 200 khz, but commands start failing at 400khz (other modules are working fine at that frequency).

if it’s a random issue, i’ve been using retrying in my python code.
Example below to schedule a hard reboot or shutdown, after a soft “sudo poweroff”
it’s improved the reliability, but still not fullproof.

@retry(wait_fixed=1000,stop_max_delay=5000)
will retry the command every 1000 ms or a maximum of 5 seconds, if there’s an exception raised.

from power_api import SixfabPower, Definition, Event
import subprocess
import time
import sys, getopt
from retrying import retry

pms = SixfabPower()
epoch = time.time()

@retry(wait_fixed=1000,stop_max_delay=5000)
def scheduleevent(opcode):
    # Remove all events
    pms.remove_all_scheduled_events(200)

    # create power off event
    event = Event()
    event.id = 1
    event.schedule_type = Definition.EVENT_INTERVAL
    event.repeat = Definition.EVENT_ONE_SHOT
    event.time_interval = 20
    event.interval_type = Definition.INTERVAL_TYPE_SEC
    event.action = opcode

    return pms.create_scheduled_event_with_event(event, 500)


def main(argv):


    scenario = ''

    try:
       opts, args = getopt.getopt(argv,"hs:")
    except getopt.GetoptError:
       print('power.py -s <scenario>')
       sys.exit(2)
    for opt, arg in opts:
       if opt == '-h':
          print('power.py -s <scenario>')
          sys.exit()
       elif opt in ("-s"):
          scenario = arg


    if scenario == "":
        print('power.py -s <scenario>')
        sys.exit(2)
    elif scenario.lower() == "reboot":
        opcode = Definition.HARD_REBOOT
    elif scenario.lower() == "shutdown":
        opcode = Definition.HARD_POWER_OFF
    else:
        print('> unsupported')
        sys.exit(2)

    print('> Scenario: ' + scenario)

    result = scheduleevent(opcode)

    if result == 1:
        subprocess.run(["poweroff"])


if __name__ == "__main__":
   main(sys.argv[1:])

In my experience if you want to communicate with the Power HAT you need to use the power_request services HTTP endpoints. Otherwise, you can’t run power_request at the same time as your own software.

My thinking there is that you run into race conditions with two processes reading from the same port and that causes issues when CRC checks that the message is complete.