Writing Standalone Python Scripts
Python can be used to write standalone scripts that you can run from the console.
Starting Proficy Code
To start the Proficy Code editor with the CIMPLICITY Python environment properly set up, you can run the following command from the Windows search box:
%cimpath%\proficy_code_launcher.exe
Proficy Code appears with no CIMPLICITY project context. This means, for example, you must fully qualify point IDs with the project name and any log_status messages will show up in the system log, not in a project log file.
Example:
You can try the following simple script:
- Enter the following script into Proficy Code and save the file with a “.py”
extension.
print("hello")
-
Run the script from the command palette by typing Ctrl+Shift+R, and then start typing Python: Run Python File in Terminal. You can also use the play button
in the upper right corner of the window.
-
Add a simple CIMPLICITY API call. IntelliSense tool appears when you type “cimplicity.” in the last statements.
import cimplicity import os print("hello") cimplicity.log_status(cimplicity.StatusSeverity.SUCCESS, os.path.basename(__file__), "hello") cimplicity.terminate_api_in_thread()
Run the code.
Result: The log message is displayed in the CIMPLICITY system status log.Note: When you use the CIMPLICITY API in a thread other than the one Event Manager calls the do_event_action method in, you must callcimplicity.terminate_api_in_thread
before the thread exits. (It may not be strictly necessary when only calling cimplicity.log_status.)
More involved script
In the following script we get and set point values.
Notes
- In the beginning of the script we use the point_get and point_set methods which are useful for quick access to points one time. If you are going to get and/or set a point value multiple times, it is more efficient to use a Point object.
- You must fully qualify the points as this CIMPLICITY environment is not associated with any project.
- Do not combine fully qualified and unqualified point references in the same client.
- A qualified point ID looks like
\\proj\pointid
. When entering that in a Python string you must escape the backslashes:\\\\proj\\pointid
. - When you run the script for the first time, CIMPLICITY will prompt you to log into the project.
- Call
cimplicity.terminate_api_in_thread
in a finally block to ensure it is always called.
import cimplicity
import os
import time
try:
print("hello")
cimplicity.log_status(cimplicity.StatusSeverity.SUCCESS,
os.path.basename(__file__), "hello")
PTVAL = "\\\\SITEA\\AirConditioner_1.Humidity"
PTVAL_SETPT = "\\\\SITEA\\AirConditioner_1.HumiditySetpoint"
val = cimplicity.point_get(PTVAL)
print(f"Current value = {val:.2f}")
val = cimplicity.point_get(PTVAL_SETPT)
print(f"Current value_setpoint = {val:.2f}")
newval = input("-> Enter new value_setpoint: ")
cimplicity.point_set(PTVAL_SETPT, newval)
val = cimplicity.point_get(PTVAL_SETPT)
print(f"Current value_setpoint = {val:.2f}")
with cimplicity.Point() as pt:
pt: cimplicity.Point # this declaration helps IntelliSense
pt.id = PTVAL
for i in range(0, 10): # range(inclusive, exclusive)
if i > 0:
time.sleep(1) # seconds
print(f"... value = {pt.get_value():.2f}"
f" (at {pt.timestamp_local})")
finally:
cimplicity.terminate_api_in_thread()
Starting Proficy Code in a Project Context- Open the project in the Workbench
- Select the Tools > Command Prompt menu item.
- In the command prompt, enter the following command to launch Proficy Code and open the
scripts folder.
%cimpath%\proficy_code_launcher.exe scripts
Note: You are recommended to put your standalone scripts in a subdirectory of the scripts directory to keep them separate.Note: In the command prompt you can also type “python” and it will run in the CIMPLICITY Python environment.
You can follow the above steps to build up a script, but this time you will not need to use fully qualified point IDs.
import cimplicity
import sys
import time
class EventHandlerState:
def __init__(self, event_action_context: cimplicity.EMEventActionContext):
# store the object attributes for later use
self.obj_attrs = event_action_context.object_attributes
print(f"__init__: obj_attrs: {self.obj_attrs}")
sys.stdout.flush()
def do_event_action(self, event_data: cimplicity.CimEMEvent):
cimplicity.log_status(
cimplicity.StatusSeverity.SUCCESS, "myscript", "running")
print(f"event_id: {event_data.event_id}")
print(f"action_id: {event_data.action_id}")
print(f"object_id: {event_data.object_id}")
print(f"timestamp_local: {event_data.timestamp_local}")
print(f"event type: {event_data.type}")
print(f"obj_attrs: {self.obj_attrs}")
if event_data.point_event is not None:
print("point event:")
pe: cimplicity.CimEMPointEvent = event_data.point_event
print(f" point ID: {pe.id}")
print(f" state: {pe.state}")
print(f" quality: {pe.quality}")
print(f" timestamp_local: {pe.timestamp_local}")
sys.stdout.flush()
def do_shutdown(self, event_data: cimplicity.CimEMEvent):
pass
def do_test():
# construct an EventHandlerState object
ea_ctx = cimplicity.EMEventActionContext(
"WORKUNIT03.OfflineForMaintEvent", "WORKUNIT03.OfflineForMaintAction",
"WORKUNIT03", {"A_HASSCANNER": "0", "A_HASBUFFER": "1"})
eh_state = EventHandlerState(ea_ctx)
# construct the CimEMEvent and CimEMPointEvent objects
ts_cimp = time.time_ns() / 100
quality = (cimplicity.QualityFlags.IS_AVAILABLE
| cimplicity.QualityFlags.IS_IN_RANGE
| cimplicity.QualityFlags.ALARMS_ENABLED
| cimplicity.QualityFlags.ACK_OCCURRED)
pt_event = cimplicity.CimEMPointEvent(
"WORKUNIT03.OfflineForMaintPoint", "value", quality, ts_cimp,
cimplicity.PointState.NORMAL, 0)
# call the do_event_action method
eh_state.do_event_action(cimplicity.CimEMEvent(
cimplicity.EventType.POINT_CHANGE, ea_ctx.object_id,
ea_ctx.event_id, ea_ctx.action_id, ts_cimp, None, pt_event,
None))
if __name__ == "__main__":
do_test()