Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into dev
Browse files Browse the repository at this point in the history
# Conflicts:
#	docs/source/develop/changelog.rst
  • Loading branch information
thorrak committed Feb 15, 2020
2 parents 30424c7 + 55ce634 commit 7d41a49
Show file tree
Hide file tree
Showing 23 changed files with 967 additions and 38 deletions.
4 changes: 2 additions & 2 deletions app/api/lcd.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ def getLCD(req, device_id):

def getPanel(req, device_id):
def temp_text(temp, temp_format):
if temp == 0:
if (temp is None) or (temp == 0):
return "--° {}".format(temp_format)
else:
return "{}° {}".format(temp, temp_format)
return "{:.1f}° {}".format(temp, temp_format)

ret = []
try:
Expand Down
15 changes: 8 additions & 7 deletions app/device_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,14 @@ def clean_device_name(self):
else:
device_name = self.cleaned_data['device_name']

try:
existing_device = BrewPiDevice.objects.get(device_name=device_name)
raise forms.ValidationError("A device already exists with the name {}".format(device_name))

except ObjectDoesNotExist:
# There was no existing device - we're good.
return device_name
# try:
# existing_device = BrewPiDevice.objects.get(device_name=device_name)
# raise forms.ValidationError("A device already exists with the name {}".format(device_name))
#
# except ObjectDoesNotExist:
# # There was no existing device - we're good.
# return device_name
return device_name

def clean(self):
cleaned_data = self.cleaned_data
Expand Down
23 changes: 16 additions & 7 deletions docs/source/develop/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) because it



[Unversioned] - Fixes
~~~~~~~~~~~~~~~~~~~~~
[Unversioned] - ThingSpeak and Grainfather Support
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Fixed
Added
---------------------

- Fixed where Fahrenheit readings coming from an iSpindel could be improperly reconverted to Fahrenheit
- Fixed issue where Tilt readings were not being properly decoded (Thanks NecroBrews!)
- Fixed issue where dashboard panels were not being updated (Thanks NecroBrews!)
- Added support for pushing data to ThingSpeak (thanks @johndoyle!)
- Added support for pushing data to Grainfather (thanks @mp-se!)


Changed
Expand All @@ -25,9 +24,19 @@ Changed
- An explicit error message will now be displayed when a user attempts to manually access the ispindel endpoint


Fixed
---------------------

- Fixed where Fahrenheit readings coming from an iSpindel could be improperly reconverted to Fahrenheit
- Lock temperature display on dashboard panels to one decimal place
- Allow updates to controller settings when controller name isn't changing (for real this time)
- Fix bug that would default all Tilts to 'Bluetooth' even when a TiltBridge was selected
- Fixed issue where Tilt readings were not being properly decoded (Thanks NecroBrews!)
- Fixed issue where dashboard panels were not being updated (Thanks NecroBrews!)


[2019-12-15] - Brewer's Friend, Brewfather, and MacOS BLE Support
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Added
---------------------
Expand Down
71 changes: 68 additions & 3 deletions docs/source/develop/push_support.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ future - support pushing via TCP (sockets)).
Supported "Push" Targets
------------------------------

Fermentrack currently supports three push targets:
Fermentrack currently supports five push targets:

- **"Generic" Push Target** - Fermentrack's "native" push format - Pushes both specific gravity & temperature data
- **Brewer's Friend** - Fermentrack's "native" push format - Pushes both specific gravity & temperature data
- **Brewfather** - Fermentrack's "native" push format - Pushes both specific gravity & temperature data
- **Brewer's Friend** - Pushes both specific gravity & temperature data associated with gravty sensors
- **Brewfather** - Pushes both specific gravity & temperature data associated with gravity sensors, as well as temperature data from BrewPi controllers with gravity sensors attached
- **ThingSpeak** - Pushes temperature data
- **Grainfather** - iSpindel push format - Pushes both specific gravity & temperature data from gravity sensors



Expand Down Expand Up @@ -95,6 +97,69 @@ Within 60 seconds, Fermentrack will begin sending data from your gravity sensor
**NOTE** - If your gravity sensor is attached to a BrewPi controller, the temperature readings from that controller will be used instead of the ones from the gravity sensor.


ThingSpeak Support
***********************

Fermentrack supports pushing data from specific sensors to a ThinkSpeak Channel. The Channel Speak API is fixed to receive fields in the channel, so the designation of each channel is already defined. This means that Field 1 is always Beer Name, Field 2 is Sensor Name, etc. To configure:

#. Log into Fermentrack and click the "gear" icon in the upper right
#. Click "Add ThingSpeak Push Target" at the bottom of the page
#. Now log into your ThingSpeak acount and on the My Channels Page select New Channel
#. Enter the data below in
::
Name - Give your Channel a Name
Description - Give your Channel a Description
Field 1 - Beer Name
Field 2 - Sensor Name
Field 3 - Temp Format
Field 4 - Beer Temp
Field 5 - Fridge Temp
Field 6 - Room Temp
Field 7 - Beer Gravity

Feel free to fill out the optional elements but only the 'field' values above are sent. The values entered are just labels for the data sent and can be customised. For example you can change 'Beer Temp' to 'My Beer (°C)'.


#. At the bottom of the page, select 'Save Channel'
#. Copy the "Write API Key" from the "API Keys" section
#. Within Fermentrack, paste the API Key you just copied into the "API Key" field
#. Set the desired push frequency and select the gravity sensor from which you want to push data
#. Click "Add Push Target"

Within 60 seconds, Fermentrack will begin sending data from to the ThingSpeak Channel. This data can be seen on the ThingSpeak 'Private View' tab in the channel page.

Grainfather Support
***********************

Fermentrack supports pushing data from specific gravity sensors (Gravity & Temperature) to Grainfather using the brew tracking API. To configure:

#. Log into your Grainfather account and select Equipment.
#. Add a Fermentation device and select iSpindel as device type. Fermentrack will push data in this format independant of what your device is. Copy the logging URL.
#. The second thing you need to do is to go to an active brew and link the device to a brew session. This is done under the headline fermentration tracking and the function "Add Tracking Device". Make note of the Name value (this is the brew ID).
#. Log into Fermentrack and click the "gear" icon in the upper right
#. Click "Add Grainfather Push Target" at the bottom of the page
#. Within Fermentrack, paste the Logging URL you just copied into the "Logging URL" field and enter the name (brew id) under the "gf_name" field.
#. Set the desired push frequency and select the gravity sensor from which you want to push data
#. Click "Add Push Target"

Within 60 seconds, Fermentrack will begin sending data from your gravity sensor to Grainfather. This data can be seen in your Grainfather account under Equipment or the Brew Session.

Grainfather Support
***********************

Fermentrack supports pushing data from specific gravity sensors (Gravity & Temperature) to Grainfather using the brew tracking API. To configure:

#. Log into your Grainfather account and select Equipment.
#. Add a Fermentation device and select iSpindel as device type. Fermentrack will push data in this format independant of what your device is. Copy the logging URL.
#. The second thing you need to do is to go to an active brew and link the device to a brew session. This is done under the headline fermentration tracking and the function "Add Tracking Device". Make note of the Name value (this is the brew ID).
#. Log into Fermentrack and click the "gear" icon in the upper right
#. Click "Add Grainfather Push Target" at the bottom of the page
#. Within Fermentrack, paste the Logging URL you just copied into the "Logging URL" field and enter the name (brew id) under the "gf_name" field.
#. Set the desired push frequency and select the gravity sensor from which you want to push data
#. Click "Add Push Target"

Within 60 seconds, Fermentrack will begin sending data from your gravity sensor to Grainfather. This data can be seen in your Grainfather account under Equipment or the Brew Session.


Implementation Notes
------------------------------
Expand Down
12 changes: 10 additions & 2 deletions external_push/admin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.contrib import admin

from external_push.models import GenericPushTarget, BrewersFriendPushTarget, BrewfatherPushTarget
from external_push.models import GenericPushTarget, BrewersFriendPushTarget, BrewfatherPushTarget, ThingSpeakPushTarget, GrainfatherPushTarget


@admin.register(GenericPushTarget)
Expand All @@ -13,4 +13,12 @@ class BrewersFriendPushTargetAdmin(admin.ModelAdmin):

@admin.register(BrewfatherPushTarget)
class BrewfatherPushTargetAdmin(admin.ModelAdmin):
list_display = ('gravity_sensor_to_push', 'status', 'push_frequency')
list_display = ('gravity_sensor_to_push', 'status', 'push_frequency')

@admin.register(ThingSpeakPushTarget)
class ThingSpeakPushTargetAdmin(admin.ModelAdmin):
list_display = ('name', 'status')

@admin.register(GrainfatherPushTarget)
class GrainfatherPushTargetAdmin(admin.ModelAdmin):
list_display = ('gravity_sensor_to_push', 'status', 'push_frequency')
14 changes: 13 additions & 1 deletion external_push/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django import forms

from external_push.models import GenericPushTarget, BrewersFriendPushTarget, BrewfatherPushTarget
from external_push.models import GenericPushTarget, BrewersFriendPushTarget, BrewfatherPushTarget, ThingSpeakPushTarget, GrainfatherPushTarget
from django.core import validators
import fermentrack_django.settings as settings

Expand All @@ -24,3 +24,15 @@ class BrewfatherPushTargetModelForm(ModelForm):
class Meta:
model = BrewfatherPushTarget
fields = ['gravity_sensor_to_push', 'push_frequency', 'logging_url']

class ThingSpeakPushTargetModelForm(ModelForm):
class Meta:
model = ThingSpeakPushTarget
fields = ['name', 'push_frequency', 'api_key', 'brewpi_to_push']



class GrainfatherPushTargetModelForm(ModelForm):
class Meta:
model = GrainfatherPushTarget
fields = ['gravity_sensor_to_push', 'push_frequency', 'logging_url', 'gf_name']
34 changes: 34 additions & 0 deletions external_push/migrations/0005_ThingSpeak_Support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.11 on 2019-11-29 21:31
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('gravity', '0004_BrewersFriend_Support'),
('external_push', '0004_Brewfather_Support'),
]

operations = [
migrations.CreateModel(
name='ThingSpeakPushTarget',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='Unique name for this push target', max_length=48, unique=True)),
('status', models.CharField(choices=[('active', 'Active'), ('disabled', 'Disabled'), ('error', 'Error')], default='active', help_text='Status of this push target', max_length=24)),
('push_frequency', models.IntegerField(choices=[(901, '15 minutes'), (1801, '30 minutes'), (3601, '1 hour')], default=900, help_text='How often to push data to the target')),
('api_key', models.CharField(default='', help_text='Brewers Friend API Key', max_length=256)),
('brewpi_to_push_id', models.ForeignKey(blank=True, default=None, help_text="BrewPi Devices to push (ignored if 'all' devices selected)", related_name='push_targets', to='app.BrewPiDevice')),
('error_text', models.TextField(blank=True, default='', help_text='The error (if any) encountered on the last push attempt', null=True)),
('last_triggered', models.DateTimeField(auto_now_add=True, help_text='The last time we pushed data to this target')),
],
options={
'verbose_name': 'ThingSpeak Push Target',
'verbose_name_plural': 'ThingSpeak Push Targets',
},
)
]
34 changes: 34 additions & 0 deletions external_push/migrations/0006_Grainfather_Support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.27 on 2019-12-23 13:58
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('gravity', '0004_BrewersFriend_Support'),
('external_push', '0005_ThingSpeak_Support'),
]

operations = [
migrations.CreateModel(
name='GrainfatherPushTarget',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('status', models.CharField(choices=[('active', 'Active'), ('disabled', 'Disabled'), ('error', 'Error')], default='active', help_text='Status of this push target', max_length=24)),
('push_frequency', models.IntegerField(choices=[(901, '15 minutes'), (1801, '30 minutes'), (3601, '1 hour')], default=900, help_text='How often to push data to the target')),
('logging_url', models.CharField(default='', help_text='Grainfather Logging URL', max_length=256)),
('gf_name', models.CharField(default='', help_text='Grainfather brew id (number)', max_length=256)),
('error_text', models.TextField(blank=True, default='', help_text='The error (if any) encountered on the last push attempt', null=True)),
('last_triggered', models.DateTimeField(auto_now_add=True, help_text='The last time we pushed data to this target')),
('gravity_sensor_to_push', models.ForeignKey(help_text='Gravity Sensor to push (create one push target per sensor to push)', on_delete=django.db.models.deletion.CASCADE, related_name='grainfather_push_target', to='gravity.GravitySensor')),
],
options={
'verbose_name': 'Grainfather Push Target',
'verbose_name_plural': 'Grainfather Push Targets',
},
),
]
36 changes: 36 additions & 0 deletions external_push/migrations/0007_fix_thingspeak.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.27 on 2020-02-03 04:28
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('app', '0009_auto_20180709_0256'),
('external_push', '0006_Grainfather_Support'),
]

operations = [
migrations.RemoveField(
model_name='thingspeakpushtarget',
name='brewpi_to_push_id',
),
migrations.AddField(
model_name='thingspeakpushtarget',
name='brewpi_to_push',
field=models.ForeignKey(blank=True, default=None, help_text="BrewPi Devices to push (ignored if 'all' devices selected)", on_delete=django.db.models.deletion.CASCADE, related_name='thingspeak_push_targets', to='app.BrewPiDevice'),
),
migrations.AlterField(
model_name='thingspeakpushtarget',
name='api_key',
field=models.CharField(default='', help_text='ThingSpeak Channel API Key', max_length=256),
),
migrations.AlterField(
model_name='thingspeakpushtarget',
name='push_frequency',
field=models.IntegerField(choices=[(59, '1 minute'), (119, '2 minutes'), (299, '5 minutes'), (599, '10 minutes'), (899, '15 minutes'), (1799, '30 minutes'), (3599, '1 hour')], default=900, help_text='How often to push data to the target'),
),
]
Loading

0 comments on commit 7d41a49

Please sign in to comment.