98 lines
3.2 KiB
Python
Executable File
98 lines
3.2 KiB
Python
Executable File
from enum import Enum
|
|
import json
|
|
import logging
|
|
|
|
import requests
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class PiShock:
|
|
"""
|
|
PiShock represents a connection to the PiShock API. See https://pishock.com
|
|
for the spec. It also allows a maximum duration and intensity to be set regardless
|
|
of the share code's limitations.
|
|
"""
|
|
|
|
PISHOCK_API = 'https://do.pishock.com/api/apioperate/'
|
|
NAME = 'PyShock'
|
|
ACTIONS = Enum('ACTIONS', ['shock', 'vibrate', 'beep'])
|
|
|
|
def __init__(self, username: str, api_key: str, code: str, name: str = '',
|
|
max_intensity: int = 50, max_duration: int = 5):
|
|
self.username = username
|
|
self.api_key = api_key
|
|
self.code = code
|
|
self.name = name if name else self.NAME
|
|
self.max_intensity = max_intensity
|
|
self.max_duration = max_duration
|
|
|
|
def shock(self, duration: int = 1, intensity: int = 5):
|
|
"""
|
|
shock sends a shock command with the given duration and intensity.
|
|
"""
|
|
|
|
self._act(self.ACTIONS.shock, duration, intensity)
|
|
|
|
def vibrate(self, duration: int = 1, intensity: int = 5):
|
|
"""
|
|
vibrate sends a vibrate command with the given duration and intensity.
|
|
"""
|
|
|
|
self._act(self.ACTIONS.vibrate, duration, intensity)
|
|
|
|
def beep(self, duration: int = 1):
|
|
"""
|
|
beep sends a beep command with the given duration.
|
|
"""
|
|
|
|
self._act(self.ACTIONS.beep, duration)
|
|
|
|
def act(self, op_readable: str, duration: int, intensity: int):
|
|
"""
|
|
act accepts a readable operation ('shock', 'vibrate', or 'beep') and the
|
|
required duration/intensity parameters as might be specified in a config
|
|
file, and fires the appropriate event.
|
|
"""
|
|
|
|
try:
|
|
self._act(self.ACTIONS[op_readable], duration, intensity)
|
|
except AttributeError as e:
|
|
logger.warning('Action not found: {}', e)
|
|
|
|
def _act(self, op: str, duration: int = 1, intensity: int = 5):
|
|
"""
|
|
_act fires the actual event by posting to the PiShock API.
|
|
"""
|
|
|
|
# Ensure we're not violating local maximums.
|
|
if duration > self.max_duration:
|
|
logger.error('%d is greater than maximum allowed duration, %d',
|
|
duration, self.max_duration)
|
|
return
|
|
if intensity > self.max_intensity:
|
|
logger.error('%d is greater than maximum allowed intensity, %d',
|
|
intensity, self.max_intensity)
|
|
return
|
|
|
|
# Build the request object.
|
|
req = {
|
|
'Username': self.username,
|
|
'Apikey': self.api_key,
|
|
'Code': self.code,
|
|
'Name': self.name,
|
|
'Op': str(op.value - 1),
|
|
'Duration': duration
|
|
}
|
|
if op in [self.ACTIONS.shock, self.ACTIONS.vibrate]:
|
|
req['Intensity'] = intensity
|
|
|
|
# Send the request. If it didn't succeed, log a warning.
|
|
logger.debug(req)
|
|
res = requests.post(self.PISHOCK_API,
|
|
json=req, headers={'Content-Type': 'application/json'})
|
|
logger.debug(res.text)
|
|
if res.status_code != 200 or res.text != 'Operation Succeeded.':
|
|
logger.warning('Error communicating with shocker: %s', res.text)
|