text: from __future__ import unicode_literals
  from django.core.urlresolvers import reverse
  from django.db import models
  from django.utils.encoding import python_2_unicode_compatible
  from django.apps import apps
  import json
  # Create your models here.
  
  @python_2_unicode_compatible
  class Device(models.Model):
      espID = models.CharField(max_length=20)
      name = models.CharField(max_length=50)
      online = models.BooleanField(default=False)
      fade_delay = models.IntegerField(default=80, verbose_name='Fade Delay')
      def status(self):
  	return 'Online' if self.online else 'Offline'
      def get_absolute_url(self):
          return reverse('esp:config', args=(self.pk,))
      def delete(self, *args, **kwargs):
  	print('deleting device')
  	super(Device, self).delete(*args, **kwargs)
          client = apps.get_app_config('esp').client
          alexa_discovery(client)
      def save(self, *args, **kwargs):
  	print('saving device')
          super(Device, self).save(*args, **kwargs)
  	client = apps.get_app_config('esp').client
  	alexa_discovery(client)
  	self.config_device()
      def soft_save(self, *args, **kwargs):
          print('saving device')
          super(Device, self).save(*args, **kwargs)
  
      def config_device(self):
  	config = {}
  	config['mqtt_delay'] = self.fade_delay
  	i=1
  	print('sending config message')
  	for pwm in self.pwm_set.all():
  		config['mqtt_topic_pwm%d'%i] = pwm.topic
  		config['mqtt_mode_pwm%d'%i] = int(pwm.nodim)
  		config['mqtt_fpwidth_pwm%d'%i] = pwm.fpwidth
  		config['mqtt_min_pwm%d'%i] = pwm.min
  		config['mqtt_max_pwm%d'%i] = pwm.max
  		i+=1
  	i=1
          for sw in self.switch_set.all():
                  config['mqtt_topic_sw%d'%i] = sw.topic
  		i+=1
  	if config:
  		client = apps.get_app_config('esp').client
      		client.publish(topic=self.espID+'/config',payload=json.dumps(config), qos=2, retain=False)
  
      def update_status(self, statusData):
  	#set online status
  	print("updating esp status:")
  	if 'online' in statusData.keys():
  		self.online = statusData['online']
  		self.soft_save()
  	#loop through device pwms, update status, and save
  	for pwm in self.pwm_set.all():
  		if pwm.topic in statusData.keys():
  			pwm.setting = statusData[pwm.topic]['setting']
  			pwm.on = statusData[pwm.topic]['on']
  			pwm.save()
  	#loop through device switches, update state, and save
  	for sw in self.switch_set.all():
  		if sw.topic in statusData.keys():
  			sw.on = statusData[sw.topic]
  			sw.save()
      def __str__(self):
  	return self.name
  
  @python_2_unicode_compatible
  class PWM(models.Model):
      device = models.ForeignKey(Device, on_delete=models.CASCADE)
      room = models.CharField(max_length=20)
      topic = models.CharField(max_length=50)
      name = models.CharField(max_length=20, default='light')
      pretty_name = models.CharField(max_length=200, default='')
      setting = models.IntegerField(default=0)
      on = models.BooleanField(default=False)
      channel = models.IntegerField(default=0)
      nodim = models.BooleanField(default=False, verbose_name='Not Dimmable')
      fpwidth = models.IntegerField(default=30, verbose_name='Fire Pulse Width')
      min = models.IntegerField(default=0, verbose_name='Min On Level')
      max = models.IntegerField(default=255, verbose_name='Max Control Level')
      def status(self):
  	return 'On' if self.on else 'Off'
      def set(self, setting, on):
  	print('setting pwm:' + self.pretty_name)
  	cmdOut = {}
  	cmdOut['deviceOn'] = on
  	cmdOut['deviceSetting'] = setting
  	client = apps.get_app_config('esp').client
  	client.publish(topic=self.topic,payload=json.dumps(cmdOut),qos=2,retain=True)
      def toggle(self):
  	self.set(self.setting,not(self.on))
      def save(self, *args, **kwargs):
          self.topic = self.room + '/' + self.name
          if self.pretty_name == '':
  		self.pretty_name = self.name
          super(PWM, self).save(*args, **kwargs)
      def get_absolute_url(self):
  	return reverse('esp:control', args=(self.pk,))
  #add function for publish
      def __str__(self):
  	return self.pretty_name
  
  @python_2_unicode_compatible
  class Switch(models.Model):
      device = models.ForeignKey(Device, on_delete=models.CASCADE)
      pwm = models.ManyToManyField(PWM, blank=True)
      room = models.CharField(max_length=20)
      topic = models.CharField(max_length=50)
      name = models.CharField(max_length=20)
      pretty_name = models.CharField(max_length=200, default='')
      on = models.BooleanField(default=False)
      channel = models.IntegerField(default=0)
      def toggle_pwm(self):
  	print('toggling pwms for switch' + self.pretty_name)
  	for pwm in self.pwm.all():
  		pwm.toggle()
      def save(self, *args, **kwargs):
  	self.topic = self.room + '/switch/' + self.name
  	if self.pretty_name == '':
  		self.pretty_name = self.name 
          super(Switch, self).save(*args, **kwargs)
  
      def __str__(self):
          return self.name
  
  def alexa_discovery(client):
      discApp = []
      dim_action = [
              "setPercentage",
              "incrementPercentage",
              "decrementPercentage"
  	    ]
  
      baseApp = dict(actions = [
              "turnOn",
              "turnOff",
              ],
          manufacturerName = "Andy Millard",
          modelName = "ESP Dimmer",
          version = "1.0",
      )
      for inst in PWM.objects.all():
          newApp = baseApp.copy()
          newApp["applianceId"] = inst.pk
          newApp["friendlyDescription"] = inst.pretty_name
          newApp["friendlyName"] = inst.pretty_name
          newApp["isReachable"] = True #could include online status here
          newApp["additionalApplianceDetails"]={"topic":inst.topic}
  	if not inst.nodim:
  	    newApp["actions"] = newApp["actions"] + dim_action
  	#print newApp["additionalApplianceDetails"]["topic"]
  	#print inst.topic
          discApp.append(newApp)
      #post to alexa discovery topic
      topic = "shadow/update"
      discApp = {"state":{"reported":{"discoveredAppliances":discApp}}}
      payload = json.dumps(discApp)
      client.publish(topic,payload = payload, qos = 1)
  
  
  