Source code for

# -*- coding: utf-8 -*-
# (c) 2015 Tuomas Airaksinen
# This file is part of Automate.
# Automate is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# Automate is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with Automate.  If not, see <>.
# ------------------------------------------------------------------
# If you like Automate, please take a look at this page:

import io

from traits.api import Str, Dict

from automate.service import AbstractUserService
from automate.program import DefaultProgram, ProgrammableSystemObject
from automate.statusobject import AbstractActuator, AbstractSensor

[docs]class PlantUMLService(AbstractUserService): """ Provides UML diagrams of the system as SVG images. Used by WebService. PLantUMLService requires either PlantUML software (which is opensource software written in Java) to be installed locally (see or it is possible to use online service of In addition you need python package :mod:`plantuml` (available via PYPI). """ #: URL of PlantUML Java Service. To use PlantUML online service, set this to '' url = Str() #: Arrow colors as HTML codes stored as a dictionary with keys: #: controlled_target, active_target, inactive_target, trigger arrow_colors = Dict( dict(controlled_target='#FF0000', active_target='#0000FF', inactive_target='#4C4C4C', trigger='#009933')) #: Background colors as HTML codes, stored as a dictionary with keys: program, actuator, sensor background_colors = Dict(dict(program='#FFFFCC', actuator='#FFCCFF', sensor='#CCFFCC'))
[docs] def write_puml(self, filename=''): """ Writes PUML from the system. If filename is given, stores result in the file. Otherwise returns result as a string. """ def get_type(o): type = 'program' if isinstance(o, AbstractSensor): type = 'sensor' elif isinstance(o, AbstractActuator): type = 'actuator' return type if filename: s = open(filename, 'w') else: s = io.StringIO() s.write('@startuml\n') s.write('skinparam state {\n') for k, v in list(self.background_colors.items()): s.write('BackGroundColor<<%s>> %s\n' % (k, v)) s.write('}\n') for o in self.system.objects: if isinstance(o, DefaultProgram) or o.hide_in_uml: continue if isinstance(o, ProgrammableSystemObject): s.write('state "%s" as %s <<%s>>\n' % (o, o, get_type(o))) s.write('%s: %s\n' % (o, o.class_name)) if isinstance(o, AbstractActuator): for p in reversed(o.program_stack): s.write('%s: %s :: %s\n' % (o, p, o.program_status.get(p, '-'))) elif hasattr(o, 'status'): s.write('%s: Status: %s\n' % (o, o.status)) if getattr(o, 'is_program', False): s.write('%s: Priority: %s\n' % (o, o.priority)) for t in o.actual_triggers: if isinstance(t, DefaultProgram) or t.hide_in_uml: continue s.write('%s -[%s]-> %s\n' % (t, self.arrow_colors['trigger'], o)) for t in o.actual_targets: if t.hide_in_uml: continue if color = 'active_target' else: color = 'inactive_target' if getattr(t, 'program', None) == o: color = 'controlled_target' s.write('%s -[%s]-> %s\n' % (o, self.arrow_colors[color], t)) s.write('@enduml\n') if filename: s.close() else: return s.getvalue()
[docs] def write_svg(self): """ Returns PUML from the system as a SVG image. Requires plantuml library. """ import plantuml puml = self.write_puml() server = plantuml.PlantUML(url=self.url) svg = server.processes(puml) return svg