mirror of
https://github.com/JoelBender/bacpypes
synced 2025-09-28 22:15:23 +08:00
269 lines
6.6 KiB
Python
269 lines
6.6 KiB
Python
#!/usr/bin/env python
|
|
|
|
"""
|
|
Raspberry Pi Binary Input and Output
|
|
This sample application is BACnet server running on a Rasbperry Pi that
|
|
associates a Button with a BinaryInputObject and a LED with a
|
|
BinaryOutputObject.
|
|
"""
|
|
|
|
from bacpypes.debugging import bacpypes_debugging, ModuleLogger
|
|
from bacpypes.consolelogging import ConfigArgumentParser
|
|
|
|
from bacpypes.core import run
|
|
|
|
from bacpypes.basetypes import BinaryPV
|
|
from bacpypes.object import (
|
|
BinaryInputObject,
|
|
BinaryOutputObject,
|
|
Property,
|
|
register_object_type,
|
|
)
|
|
from bacpypes.errors import ExecutionError
|
|
|
|
from bacpypes.app import BIPSimpleApplication
|
|
from bacpypes.local.device import LocalDeviceObject
|
|
|
|
from gpiozero import Button, LED
|
|
|
|
# some debugging
|
|
_debug = 0
|
|
_log = ModuleLogger(globals())
|
|
|
|
# button number, binary input object instance number
|
|
button_list = [(2, 2)]
|
|
|
|
# LED number, binary output object instance number
|
|
led_list = [(17, 17)]
|
|
|
|
#
|
|
# Mock classes
|
|
#
|
|
|
|
'''
|
|
# We may want to look into the mock pin class of gpiozero.
|
|
# It will allow for testing without using an RPI board.
|
|
|
|
class Button:
|
|
def __init__(self, button_id):
|
|
pass
|
|
|
|
|
|
class LED:
|
|
def __init__(self, led_id):
|
|
pass
|
|
'''
|
|
|
|
#
|
|
# BIPresentValue
|
|
#
|
|
|
|
|
|
@bacpypes_debugging
|
|
class BIPresentValue(Property):
|
|
def __init__(self, identifier):
|
|
if _debug:
|
|
BIPresentValue._debug("__init__ %r", identifier)
|
|
Property.__init__(
|
|
self, identifier, BinaryPV, default=False, optional=False, mutable=False
|
|
)
|
|
|
|
def ReadProperty(self, obj, arrayIndex=None):
|
|
if _debug:
|
|
BIPresentValue._debug("ReadProperty %r arrayIndex=%r", obj, arrayIndex)
|
|
|
|
# access an array
|
|
if arrayIndex is not None:
|
|
raise ExecutionError(
|
|
errorClass="property", errorCode="propertyIsNotAnArray"
|
|
)
|
|
|
|
|
|
###TODO: obj._button is the Button object
|
|
|
|
if _debug:
|
|
BIPresentValue._debug(" - read button: %r", obj._button)
|
|
|
|
if obj._button.is_pressed:
|
|
return "active"
|
|
|
|
else:
|
|
return "inactive"
|
|
|
|
def WriteProperty(self, obj, value, arrayIndex=None, priority=None, direct=False):
|
|
if _debug:
|
|
BIPresentValue._debug(
|
|
"WriteProperty %r %r arrayIndex=%r priority=%r direct=%r",
|
|
obj,
|
|
value,
|
|
arrayIndex,
|
|
priority,
|
|
direct,
|
|
)
|
|
|
|
raise ExecutionError(errorClass="property", errorCode="writeAccessDenied")
|
|
|
|
|
|
#
|
|
# RPiBinaryInput
|
|
#
|
|
|
|
|
|
@bacpypes_debugging
|
|
@register_object_type
|
|
class RPiBinaryInput(BinaryInputObject):
|
|
|
|
properties = [BIPresentValue("presentValue")]
|
|
|
|
def __init__(self, button_id, **kwargs):
|
|
if _debug:
|
|
RPiBinaryInput._debug("__init__ %r %r", button_id, kwargs)
|
|
BinaryInputObject.__init__(self, **kwargs)
|
|
|
|
# create a button object
|
|
self._button = Button(button_id)
|
|
|
|
|
|
#
|
|
# BOPresentValue
|
|
#
|
|
|
|
|
|
@bacpypes_debugging
|
|
class BOPresentValue(Property):
|
|
def __init__(self, identifier):
|
|
if _debug:
|
|
BOPresentValue._debug("__init__ %r", identifier)
|
|
Property.__init__(
|
|
self, identifier, BinaryPV, default=False, optional=False, mutable=True
|
|
)
|
|
|
|
def ReadProperty(self, obj, arrayIndex=None):
|
|
if _debug:
|
|
BOPresentValue._debug("ReadProperty %r arrayIndex=%r", obj, arrayIndex)
|
|
|
|
# access an array
|
|
if arrayIndex is not None:
|
|
raise ExecutionError(
|
|
errorClass="property", errorCode="propertyIsNotAnArray"
|
|
)
|
|
|
|
|
|
###TODO: obj._led is the LED object
|
|
if _debug:
|
|
BOPresentValue._debug(" - read led: %r", obj._led)
|
|
|
|
if obj._led.value == 1:
|
|
return "active"
|
|
else:
|
|
return "inactive"
|
|
|
|
|
|
def WriteProperty(self, obj, value, arrayIndex=None, priority=None, direct=False):
|
|
if _debug:
|
|
BOPresentValue._debug(
|
|
"WriteProperty %r %r arrayIndex=%r priority=%r direct=%r",
|
|
obj,
|
|
value,
|
|
arrayIndex,
|
|
priority,
|
|
direct,
|
|
)
|
|
|
|
# access an array
|
|
if arrayIndex is not None:
|
|
raise ExecutionError(
|
|
errorClass="property", errorCode="propertyIsNotAnArray"
|
|
)
|
|
|
|
###TODO: obj._button is the Button object
|
|
if _debug:
|
|
BOPresentValue._debug(" - write led: %r", obj._led)
|
|
|
|
#raise ExecutionError(errorClass="property", errorCode="writeAccessDenied")
|
|
|
|
if value == "active":
|
|
obj._led.on()
|
|
elif value == "inactive":
|
|
obj._led.off()
|
|
else:
|
|
### TODO: insert correct value error. Below is a placeholder.
|
|
print("invalid value for led. Use 'active' to turn on or 'inactive' to turn off.")
|
|
|
|
|
|
#
|
|
# RPiBinaryOutput
|
|
#
|
|
|
|
|
|
@bacpypes_debugging
|
|
@register_object_type
|
|
class RPiBinaryOutput(BinaryOutputObject):
|
|
|
|
properties = [BOPresentValue("presentValue")]
|
|
|
|
def __init__(self, led_id, **kwargs):
|
|
if _debug:
|
|
RPiBinaryOutput._debug("__init__ %r %r", led_id, kwargs)
|
|
BinaryOutputObject.__init__(self, **kwargs)
|
|
|
|
# make an LED object
|
|
self._led = LED(led_id)
|
|
|
|
|
|
#
|
|
# __main__
|
|
#
|
|
|
|
|
|
def main():
|
|
# parse the command line arguments
|
|
args = ConfigArgumentParser(description=__doc__).parse_args()
|
|
|
|
if _debug:
|
|
_log.debug("initialization")
|
|
if _debug:
|
|
_log.debug(" - args: %r", args)
|
|
|
|
# make a device object
|
|
this_device = LocalDeviceObject(
|
|
objectName=args.ini.objectname,
|
|
objectIdentifier=("device", int(args.ini.objectidentifier)),
|
|
maxApduLengthAccepted=int(args.ini.maxapdulengthaccepted),
|
|
segmentationSupported=args.ini.segmentationsupported,
|
|
vendorIdentifier=int(args.ini.vendoridentifier),
|
|
)
|
|
|
|
# make a sample application
|
|
this_application = BIPSimpleApplication(this_device, args.ini.address)
|
|
|
|
# make the buttons
|
|
for button_id, bio_id in button_list:
|
|
bio = RPiBinaryInput(
|
|
button_id,
|
|
objectIdentifier=("binaryInput", bio_id),
|
|
objectName="Button-%d" % (button_id,),
|
|
)
|
|
_log.debug(" - bio: %r", bio)
|
|
this_application.add_object(bio)
|
|
|
|
# make the LEDs
|
|
for led_id, boo_id in led_list:
|
|
boo = RPiBinaryOutput(
|
|
led_id,
|
|
objectIdentifier=("binaryOutput", boo_id),
|
|
objectName="LED-%d" % (led_id,),
|
|
)
|
|
_log.debug(" - boo: %r", boo)
|
|
this_application.add_object(boo)
|
|
|
|
_log.debug("running")
|
|
|
|
run()
|
|
|
|
_log.debug("fini")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|