code: def write_puml(self, filename=''):
          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 o.active:
                          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()