TheGreydiamonds Blog

Category: Uncategorized (Page 1 of 2)

Enabling “hosted” features in outline

Attention

The initial guide stopped working as of version v0.72.0 due to PR#5742 which removed the variables from the .env file. I’ve updated this article to include the new way of enabling these features – but kept the old text.

A few days ago I discovered a nice Notion alternative called “Outline“. It seemed to provide a nice feature set while also being self-hosted. The setup was somewhat cumbersome, as it needs an S3 Object storage, auth provider, postgres DB and Redis server. After setting up Keycloak for auth and MinIO for S3 Object storage I was ready to go.

But there was one thing missing I knew from Notion—multiple workspaces and switching between them. The UI looked like it supported context switching, though no “Create New Workspace” can be found. Digging through the web demo I found the function. The hosted version seems to support it while the self-hosted doesn’t weird. After looking through Outline’s Github issues I discovered someone complaining about a semi-working “Create workspace” button.

A screenshot of the working "New Workspace" button in Outline
A screenshot of the working “New Workspace” button

Configuration options to get Outline working

Most configuration is done using the .env file. One option which caused the semi-working button to show up was DEPLOYMENT=hosted. And I was able to confirm this aforementioned behaviour. Indeed a “Create Workspace”-button showed up. Creating a new Workspace, however, caused weird behaviour where I was trapped in the new Workspace, unable to switch.

Looking through the source code there was another interesting option SUBDOMAINS_ENABLED=true. Huh, I wonder what this does I thought while flicking it on.

Upon visiting the outline subdomain I was greeted with a redirect to a subdomain <workspace>.outline.domain.tld. This felt like the final stretch. I made a new certificate for *.outline subdomains and set up nginx to point them to the application as well.

And boom – I got a “hosted-only” feature working on a self-hosted instance.

Cool – but how to enable these features?

Before version v0.72.0 these features could be enabled by changing variables in the .env file. As of PR#5742 this no longer works and code modification is required.

There are two points in the source code where the system decides whether or not it is running a “cloud-hosted” environment. We need to modify the code, to make it think that we always run in such a hosted env.

Begin by modifying the file “app/utils/isCloudHosted.ts” where you need to replace these lines:

const isCloudHosted = [
  "https://app.getoutline.com",
  "https://app.outline.dev",
  "https://app.outline.dev:3000",
].includes(env.URL);

with this single line:

const isCloudHosted = true;

Next edit the file “server/env.ts”, where you replace:

return [
      "https://app.getoutline.com",
      "https://app.outline.dev",
      "https://app.outline.dev:3000",
    ].includes(this.URL);

with this simple bit:

return true;

These are all the steps necessary in order to get these hosted features back. I recommend you run yarn build after this for good measure.

Cool – but how do I do it? – The old (and broken) way

First, add these lines to your configuration:

DEPLOYMENT=hosted
SUBDOMAINS_ENABLED=true

Now make sure you have SSL certificates for the subdomain you want to use. In my case *.outline.domain.tld. You can use certbot with the cloudflare-dns-challenge plugin to request fitting certificates.

Next, you need to configure your nginx webserver to properly handle the new request.

This is the config I’m using. This might not be perfect for your installation but should probably also work.

I hope this helps someone out there and saves them at least a little time!

A first go at projection mapping – What we’ve learned

A few months ago (at Halloween to be specific) a friend of mine and I had the idea to do some projection mapping after licking blood while doing a small-scale test at his house (link coming soon). We came up with the idea of projection onto the front of my school. “Yea sure”, I sarcastically replied. However, a few weeks later I came back to the idea and we decided that we wanted to have a go at it.

I didn’t think I’d get this far

The first step was convincing my school to allow me to do it. I talked to one of my favourite teachers about the idea first and he seemed to like it. So I made an appointment with our headteacher. And after presenting the idea he was all for it. That was easier than expected. The biggest issue was getting power to the front of our school – in the middle of the school holidays. Oh yeah did I mention that we decided to do it on New years eve?

The next important step was getting equipment. My friend could get two crappy projectors from his school. That was not nearly enough. So I reached out to the boss of a local event tech company who I knew. He swiftly agreed to give me his biggest projector (with a lens!) for free for a few days.

Due to some concerns we also reached out to MSS-Security, a local security company and they agreed to be there for the evening if we advertise them in some way.

So now we had:

  • four projectors
  • a PA system (shout-out to wentzbeatz btw)
  • power in front of our school (courtesy of our cool custodian)
  • and a (hopefully) sturdy tent (foreshadowing….)

Now that we had all components together it was time to start making content.

Making content

The first step was to get a rough idea of how to lay out the content. So I headed out to create a 3D scan of the school. That worked semi-well. Turns out 500 photos are bearly enough. The model had a lot of holes and looked more like swiss cheese rather than a proper model. After importing that model into Blender we created an orthographic render of the building.

A guide we used to align media with the building

We quickly decided on how we wanted to lay out the show time-wise. It should contain some narration and music-driven elements. Most content was created by XilefTech due to the simple fact of me being very busy.

Additionally, we only created the content a few days before the event. So if we were to do it again, we would need to take a lot more time for content preparation. This time crunch lead to us having the remove a segment because it decided to not render at the last minute and we had no time to try and debug it.

Finally, we put everything into MadMapper. MadMapper allowed us to easily combine the pre-rendered content with render-on-the-fly content. So while no preprepared show was running we could create content on the fly without much worry. We rented a one-seat license for just that event. Some time ago we reached out to MadMapper in the hope to get some kind of sponsorship, sadly they responded to us that they stopped sponsoring artists (in the most generic E-Mail template there is…).

Running the event

Due to the sheer amount of stuff, we had to transport we needed to take two car rides. On our first go, we brought a tent and some speakers which I set up while my colleague went to get the next load. We set aside around one and a half hours for setup. After setting up the tent and our speakers the next step on our list was to set up our big 20.000 ANSI Lumen Panasonic Projector. After placing it in a central spot and adjusting it we were blown away by how much it actually covered. We had done our fair share of maths beforehand and were always a little scared of not having enough projectors.

We ran the setup with two laptops, only giving us two outputs. You might have noticed there is a small mismatch between the number of projectors we have and the outputs we can provide. So we brought two Raspberry PIs to act as NDI receivers. We were running Dicaffine, and it worked for the most part, though it seems like even small drop-outs cause it to lose connection completely. The official NDI tools are sadly not available for Linux. We briefly considered using Windows IoT, however, we couldn’t get it working in time. We’ve conducted tests beforehand and it had always worked “fine”, however, something was not running well that evening. The Pis were cutting out most of the time. It didn’t hurt the show too much as they were providing data to the two weak projectors to the left and right of our projection area.

In retrospect using two not-that-high-power laptops wasn’t a very splendid idea either. However, it mostly worked. Running some content we had stuttering issues due to the power of the laptop. We had another stronger laptop with us, however, it had issues providing data to our main projectors. The projector supported some kind of 3D projection. Windows did really not like that.

Apart from some minor performance issues, the evening went through okay. We were semi-lucky with the weather. It had just stopped raining in the early noon and everything looked fine. However, there were some strong wind gusts which we thought of as non-issues. Turned out we were pretty wrong about that. After about half the time our tent was blown away, we managed to catch it before flying off, though one of the primary stands of the tent broke.

Summary

We all really enjoyed the evening. However, if we were to do it again, we would need a whole lot more time for preparation and a little more capable equipment. We even managed to get a shoutout on my school’s website (link to the article, german).

Gallery

Here are a few impressions of the evening and a video:

Reverse engineering a Moonside Lighthouse Light

Working in Progress

This article is still a work in progress, which means it will be updated in the future. Images may be missing captions or alt-texts. There might also be some language weirdness.

I’ve had a Moonside Lighthouse lying around for some time. It’s a pretty nice-looking light fixture, however, there was no way to integrate it into my Homeassistant setup. I’ve had a shot at reverse engineering it’s communication and here are my results:

Trying the network route

Lighthouse is able to join your WiFi-Network for remote control, because of that I was hoping to find some open network port using Nmap. A quick scan showed nothing, meaning that this way is likely a dead end.

However, this digging surfaced one interesting piece of information about its MAC Address, which belongs to the Espressif MAC range (meaning it’s likely something ESPy).

Internet

There also exists a public API which enables you to control the fixture remotely. I was unable to get it working, also I would like to be able to control my light locally. I have not explored this route further.

Bluethooth

After it became clear that networking is sadly not an option I started looking into Bluethooth. The App uses BLE to talk to the lamp. My first attempt was to use the nRF Connect tool to reads its characteristics.

A screenshot made in the nRF connect app showing three services. The first being a "Generic Attribute" with UUID: 0x1801.
The next one being a "Generic Access" with the UUID 0x1800.
The last one is "Nordic UART Service" with UUID: 6e400001-b5a3-f393-e0a9-e50e24dcca9e
A screenshot from the nRF connect app where the first service ("Generic Access") was expanded. It's shows three attributes, "Device Name", "Apperance" and "Central Address Resolution". The device name is "MOONSIDE-T1", apperance is "[0] Unknown", address resoultion is not supported.

None of these characteristics were helpful, except one which piqued my interest., “Nordic UART Service”, I’ve never heard of that before, though it seems fairly helpful. Using the nRF toolbox I was able to connect to it via BLE UART. That itself worked fine, however, brute-forcing commands were not useful as there was no response to anything.

Snooping the traffic

The next logical step was to snoop on the traffic between the android app and the hardware counterpart. That proved to be not as easy as it sounds, in the end, I used Wireshark to look at the traffic.

First step was to enable Bluetooth Snooping in the developer settings. Then after some debugging and using this command:

db shell su -c "'nc -s 127.0.0.1 -p 8872 -L system/bin/tail -f -c +0 data/misc/bluetooth/logs/btsnoop_hci.log'"

The interface showed up in Wireshark. Though you need to android dump androiddump module for Wireshark.

Info

It seems like your device needs to be rooted for this to work, I’ve seen contradicting information about that, however.

Finally, I was able to see communication with a device called Espressi_2a:9d:5a, which looks suspiciously like the device in question.

Deconstructing the communication

The became apparent that the app talks in clear text with the light fixture. These commands started showing up:

CommandDescription
LEDOFFTurns the light off
LEDONTurns the light on
BRIGHXXXBrightness, replace XXX with number (max: 120, min:0)
COLORRRRGGGBBB XXXSets the colour, replace R with red value, G with green value and B with blue value (0-255), optional X brightness argument
THEME.????????Sets a theme
PIXEL,ID,XXX COLOR?Set a pixel, where ID is the pixel (0-89), XXX is the brightness and COLOR is the colour in an unknown format
MODEPIXELApplies pixel settings

Mind you the values of for example the ID range might be different between devices, however I will probably not buy more devices just to prove my theory.

Some things are also just unknown. I do not understand how sound-enabled modes work (yet!). It sends some number string and that’s it. I was also unable to figure out the COLOR format for pixel setting, it is six digits ranging from 0-9.

Themes

Themes are a whole different topic. They are way more configurable than the app gives you options. Here is a list of the themes from the app:

Theme nameThemenick
RAINBOW1.20,Rainbow One
FIRE1.20,Night Fire
THEME.THEME1.162,255,174,255,85,90,Blue Raspberry
THEME.WAVE1.255,0,0,255,0,255,Pink Ball
THEME.BEAT1.255,0,0,0,255,0,0,0,255,Dancing Beat
THEME.GRADIENT2.0,255,0,20,65,20,200,200,200,Green Land
THEME.THEME3.0,0,200,0,100,200,100,0,200,200,0,0,200,06,100,120,200,0,Candy Mix
THEME.THEME1.255,0,0,0,0,255,My Moon
THEME.BEAT2.255,255,0,0,0,255,Bouning Stars
THEME.GRADIENT1.0,255,0,255,0,0,Christmas Blend
THEME.RAINBOW3.0,Blending Rainbow
THEME.THEME2.138,35,135,242,113,33,Wire Tap
THEME.COLORDROP1.10,100,255,200,200,200,Raining Blue
THEME.TWINKLE1.255,0,0,0,0,255,Twinkle Star
THEME.FIRE2.0,0,0,0,255,0,200,0,0,255,0,0,Green Fire
THEME.GRADIENT2.145,3,245,255,25,194,191,176,187,Purple Cake
THEME.GRADIENT1.150,0,255,255,214,243,Purple Dream
THEME.LAVA1.200,0,0,50,0,0,0,0,255,Blue Lava
THEME.LAVA1.20,255,2,255,100,0,255,0,60,MacMac
THEME.THEME1.168,255,120,120,255,214,Summer Glow
THEME.BEAT2.7,200,249,13,34,135,Dancing Ocean
THEME.PALETTE2.0,0,200,0,100,200,100,0,200,200,0,0,2006,0,100,120,200,0,Colorful Swinging
THEME.GRADIENT1.255,80,0,0,0,0,Late OJ
THEME.BEAT1.255,190,100,255,190,100,Shining Beat
THEME.GRADIENT1.255,208,50,100,100,100,Margo
THEME.RAINBOW2.20,Rising Rainbow
THEME.THEME5.200,20,150,0,60,255,Vibrant City
THEME.COLORDROP1.0,255,0,255,8,130,Rose Drop
THEME.FIRE2.0,0,0,31,255,110,155,252,212,255,255,255,Ghost Fire
THEME.GRADIENT1.255,0,0,200,200,200,Pink Dawn
THEME.PULSING1.255,0,20,20,20,255,Super Pulsing
THEME.PULSING1.115,255,182,250,255,204,Super Limeade
THEME.GRADIENT1.147,71,255,255,102,50,Galaxy Purple
THEME.GRADIENT2.255,0,0,50,190,10,0,160,200,Nemo Green
THEME.LAVA1.0,183,255,0,0,0,255,255,255,Cool Sky
THEME.THEME1.0,0,255,255,0,255,Distant Night
THEME.FIRE2.0,0,0,255,0,0,0,255,0,0,0,255,Rainbow Fire
THEME.GRADIENT2.255,0,0,80,20,0,200,200,200,Volcano Ice Cream
THEME.THEME1.255,0,0,0,255,0,Wild Watermelon
THEME.TWINKLE1.255,0,0,0,180,0,Twinkle Christmas
THEME.GRADIENT2.255,66,20,255,66,20,8,217,255,Ali
THEME.GRADIENT1.198,255,221,247,45,50,Megatron
THEME.GRADIENT1.255,0,0,0,50,200,Blue Raspberry
THEME.GRADIENT1.0,255,0,200,200,200, WizardVibe Beat
THEME.THEME4.255,50,0,0,90,220,Orange Ocean
THEME.GRADIENT2.0,255,0,255,0,0,100,0,0,Jingle Bell
THEME.LAVA1.255,25,0,100,30,0,255,150,0,Glowing Lava
THEME.GRADIENT2.59,250,229,255,85,0,255,0,20,Celebration Candy
THEME.GRADIENT2.0,0,255,30,102,128,255,255,255,Ice Mountain
THEME.GRADIENT1.86,255,119,98,38,210,Magic Blend
THEME.GRADIENT1.255,255,30,36,255,65,Martini
THEME.PALETTE1.0,Color Wheel
THEME.LAVA1.255,0,0,60,60,60,0,255,0,Christmas Snow
THEME.GRADIENT1.195,255,210,2,9,19,Petrol
THEME.GRADIENT1.0,150,255,200,200,200,Aqua Wave
THEME.FIRE2.0,0,0,255,0,0,0,0,255,255,255,255,Magic Fire
THEME.GRADIENT2.8,175,212,178,37,247,242,12,188,WaterShine
All themes

Sound-activated modes seem to be variations of themes. These have yet to be mapped. However, they commonly start with M and another number following that. After that, there are colour arguments again.

Modifiying theme data

There are a few theme “keywords” which can then be mixed with arguments. These are: THEME1, THEME2, THEME3, THEME4, THEME5, WAVE1, BEAT1, BEAT2, BEAT3, GRADIENT1, GRADIENT2, RAINBOW1, RAINBOW2, RAINBOW3, TWINKLE1, FIRE2, COLORDROP1, LAVA1, COLORDROP1, PULSING1

Following these theme keywords are blocks of colour, most in this format: (yes they end in a ,)

THEME.THEME1.RRR1,GGG1,BBB1,RRR2,GGG2,BBB2,

It seems like every theme’s colour values change different aspects of the effect. (more will be added below over time)

ThemeDescription
FIRE2.BBB,BBB,BBB,111,111,111,222,222,222,333,333,333B is the “background” or base colour of the effect, you can leave it with 0s, meaning it will stay off. The rest 1-3 are other effect colours.

Building a smart home interface

I’ve built a basic Sketch which connects to the WiFi network. Have a look below! (I will continue working on this sketch)

(If there is nothing above this text make sure to enable experience cookies!)

Sending, Receiving and verifying messages sent over LoRa using RFM95W

In this blog post, I will be using an RFM95W LoRa chip together with an ESP8266/ESP32 to transmit (receive/send) data and check if this data is complete.

Preperations

My first course of action was to get two ESPs ready to send/receive data via LoRa. If you have trouble or are looking for a dedicated tutorial have a look at these posts for the ESP32 and ESP8266. I have decided that my ESP8266 will send data and my ESP32 receive this data.

As a simple first test, I used the provided example sketches. This worked pretty well, I received my packets on the ESP32. After looking at it for a while I found a problem: RF has (like everything else) the problem of packet corruption, it doesn’t happen very often but when it does, it gets annoying.

The Problem

Our main problem is data corruption, my goal for this is to detect data corruption and ignore the received message. Let’s take an example: You have a simple LoRa node connected to a motion sensor, we send a data packet containing the battery state and the motion sensor’s state, like so:

0;1

The zero being the motion state (0, meaning false / no motion), and the 1 being the battery health (1, meaning true / healthy). Now let’s imagine there is a packet corruption and the first part (0;) gets removed, now our first item is a 1. If the receiver doesn’t notice the broken package, it might be that a false alarm gets triggered. After all the first bit, so motion, was true. This is the reason we need to check if a package is actually healthy.

My idea was to send the data and append some kind of hash to it. I will be using a sha1 hash for this, as ESPs can calculate this hash pretty easily, even though it’s a little overkill for this application. My new package will now look like this:

Actual data here;hash
Hello 4;a94a8fe5ccb19ba61c4c0873d391e987982fbbd3

Okay, after making the theory clear let’s implement it!

The implementation

Starting with my sending code, it looks like this:

Use the right frequencies for your region

If you adapt this code please check if you use the right frequency. Different regions use different frequencies for LoRa. Please check your local guidelines. Europe uses 868MHz (868E6). Update your LoRa.begin line! Here is a useful table by TTN.

#include <SPI.h>
#include <LoRa.h>
#include "Hash.h"

int counter = 0;
// - Pin configs - ESP32 -
// #define ss 5
// #define rst 14
// #define dio0 2

// - Pin configs - ESP8266 -
#define ss 4    // D2
#define rst  5 // D1
#define dio0 -1 // Disabled



void setup() {
  Serial.begin(115200);
  while (!Serial);
  delay(1000);

  Serial.println("LoRa Sender");
  // Setup LoRa transceiver module
  LoRa.setPins(ss, rst, dio0);
  if (!LoRa.begin(868E6)) {
    Serial.println("Starting LoRa failed!");
    delay(5000);
    Serial.println("Now waiting for Watchdog to restart");
    while (1);
  }else{
    Serial.println("Starting LoRa successful");
    }
  
}

// Sends a string every 5000ms (5 seconds)
void loop() {
  Serial.print("Sending packet: ");
  Serial.println(counter);

  // send packet
  LoRa.beginPacket();
  String result = sha1("hello " + String(counter)); // Creating the hash value for our string
  LoRa.print("hello ");
  LoRa.print(counter);
  LoRa.print(";");
  LoRa.print(result);
  LoRa.endPacket();

  counter++;

  delay(5000);
}

This will send our packets with the hash appended. For the next bit, we will need to receive the message and check if the supplied hash is correct.

#include <SPI.h>
#include <LoRa.h>
#include <Hash.h>
// - Pin configs - ESP32 -
#define ss 5
#define rst 14
#define dio0 2

// - Pin configs - ESP8266 -
// #define ss 4    // D2
// #define rst  5 // D1
// #define dio0 -1 // Disabled

// Taken from https://forum.arduino.cc/t/arduino-split-funktion-eines-strings/595753
String split(String s, char parser, int index) {
  String rs = "";
  int parserIndex = index;
  int parserCnt = 0;
  int rFromIndex = 0, rToIndex = -1;
  while (index >= parserCnt) {
    rFromIndex = rToIndex + 1;
    rToIndex = s.indexOf(parser, rFromIndex);
    if (index == parserCnt) {
      if (rToIndex == 0 || rToIndex == -1) return "";
      return s.substring(rFromIndex, rToIndex);
    } else parserCnt++;
  }
  return rs;
}

void setup() {
  Serial.begin(115200);
  while (!Serial);

  Serial.println("LoRa Receiver");
  LoRa.setPins(ss, rst, dio0);
if (!LoRa.begin(868E6)) {
    Serial.println("Starting LoRa failed!");
    delay(5000);
    Serial.println("Now waiting for Watchdog to restart");
    while (1);
  }else{
    Serial.println("Starting LoRa successful");
    }
}

void loop() {
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packet
    Serial.print("Received packet '");

    // Create a string of the incoming message
    String message = "";
    while (LoRa.available()) {
      message += (char)LoRa.read();
    }
    Serial.print(message);
 
    String result = sha1(split(message, ';', 0)); // Take the first element, the raw message and hashing it
    String tempy = message;
    tempy.replace(split(message, ';', 0) + ";", ""); // Now replace the message so only the hash is left
    if (result == tempy) { // Is the hash the same?
      Serial.print(" Hash ok ");
    } else {
      Serial.print(" Hash fail, expectd hash ");
      Serial.print(tempy);
      Serial.print(" "); 
      Serial.print(split(message, ';', 1)); 
      Serial.print(" "); 
    }

    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
  }
}

Using the hash library on ESP32

For some reason, the ESP32 does not implement the same hash functions as the ESP8266. Therefore I used this third party library to get the same functinality.

After running the code for a while I got this output on my receiver serial console. It worked! Sadly it’s pretty hard to break a package on purpose, but I checked it and this code works, however, I sadly don’t have a screenshot of a broken transmission.

This concludes my little experiment/project here, I have achieved my goal to detect broken transmissions and that’s it! I hoped this helped someone on their way.

Getting started with RFM95W, LoRa and ESP8266

In this blog post I will be introducing you to LoRa using the RFM95W module with an ESP8266, so let’s get started. I also wrote this article for the ESP32, read it here.

First, we should talk about what LoRa is and what it stands for. LoRa stands for Long Range and as the name suggests one of its main aspects is its considerable range. However, we need to make a distinction between LoRa and LoRaWAN. In this tutorial, I will be talking about LoRa. LoRaWAN adds another layer of authentification. Services like TheThingsNetwork (TTN) use LoRaWAN. However, LoRa is easier to use and understand for this tutorial.

Hardware used / Preparation

For this tutorial, I will be using an RFM95W module with an ESP8266. This is a bit tricky because there are some weird road bumps. The RFM95W is our LoRa communication chip. I’ve got my ESP from the german seller AZ-Delivery (I’m not affiliated with them in any way nor do I get any money from them for mentioning their name). My RFM95W comes from Amazon.

For this, I will assume that your Arduino IDE is set up to work with ESP8266s. If not here is a tutorial to do it.

Wiring

The wiring diagram

If you have a different ESP you can check the documentation supplied below for further details.

Now get started, for real

As a first step build up the setup shown above. Next, you need to install the LoRa Libary by Sandeep Mistry. More documentation is available here.

This code is actually the library’s example code modified to give a little more output.

Use the right frequencies for your region

Different regions use different frequencies for LoRa. Please check your local guidelines. Europe uses 868MHz (868E6). Update your LoRa.begin line! Here is a table by TTN.

#include <SPI.h>
#include <LoRa.h>

int counter = 0;
// - Pin configs -
#define ss 4    // D2
#define rst  5 // D1
#define dio0 -1

void setup() {
  Serial.begin(115200);
  while (!Serial);
  delay(1000);

  Serial.println("LoRa Sender");
  // Setup LoRa transceiver module
  LoRa.setPins(ss, rst, dio0);
  
  if (!LoRa.begin(868E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }else{
    Serial.println("Starting LoRa successful");
    }
  
}

// Sends a string every 5000ms (5 seconds)
void loop() {
  Serial.print("Sending packet: ");
  Serial.println(counter);

  // send packet
  LoRa.beginPacket();
  LoRa.print("hello ");
  LoRa.print(counter);
  LoRa.endPacket();

  counter++;

  delay(5000);
}

Information

I was unable to make the DIO0 work. This is why this sketch does not use it. Be aware!

I’ve had some issues using the code out-of-the-box. Some problems are due to the code lacking a lot of verbosity and some are due to user problems. The code above fixes one of the issues, verbosity. The other one is addressed below.

Tip

Please note that the library expects GPIO pins, not D pins. More information is available here.

After changing your frequencies and making sure that you use the right board, hit the upload button. After the upload is done open your serial console, select 115200 baud. Then you should see this output:

A arduino serial output window.
The serial output

And finally, your ESP is sending LoRa. Some of the items I need for receiving are stuck in shipping this has to wait for another day. However, below is a short paragraph for those who already own an SDR.

Does this even work? For people with SDRs

This paragraph is made for people who own SDRs (SoftwareDefinedRadio). For this, I’m using a VM running ParrotOS. This image comes preinstalled with SDR++. GNUradio and a bunch of extensions for GNUradio. These extensions also contain gr-lora, which I will be using here. Following this tutorial in the wiki, you should be able to set up your workspace to receive LoRa messages. Please also remember to use the right frequency. The results looks something like this:

With this setup, I was able to use a pretty good range, even though I only used a so-called random wire antenna. This also shows how some packets are missing some data. This shows why you should always use the hash numbers to verify that the received packet is healthy. I will be talking about hashes sometime in the future.

The result as seen in SDR++

I hope I could get you on your way into the interesting world of LoRa.

Fixing a broken ESP8266 (NodeMCU)

We’ve all done it before, accidentally shorting Vin (Voltage input) and GND (Ground) on an ESP8266. I have done it as well thinking: How should this break an ESP8266? It turns out by destroying the reverse polarity diode. These are not my findings btw, by these people figured it out. But let’s get to work. Here is the current state:

Broken diode marked with a red rectangle

The thing marked with a red box is the broken diode. This is the thing that needs to be fixed. First step: Remove it.

In the next step, we will replace it with a new diode called wire.

The diode replaced with a wire

This fixed my broken ESP8266 and brought it back to life. I hope someone can use this.

Cloudflare Rocket loader or why my Nextcloud won’t work

This article is about Cloudflare Rocket loaders passion to break Nextcloud (and apparently PhpMyAdmin for some people) and how to fix it.

I have installed Nextlcoud for some testing purposes some time ago. As a side note; Yes, I’m using Cloudflare for DNS. And was surprised by Nextcloud’s clean UI, consisting of only the logo and a background image.

A very clean UI

I know one of the last updates overhauled Nextclouds UI, but this is a little too clean, even in my taste. To diagnose the issues I swiftly opened the Javascript console hidden away in the inspect element dialogue. One of the major error messages I saw was the browser being unable to load a library called “RocketLoader”. After some searching, I found out that others have also run into this problem before, but Nextcloud does not use RocketLoader. After going through Cloudflare’s Speed setting in boredom one day I saw an option titled “Enable Cloudflare Rocket Loader”, which was enabled. I turned the ticked box off, and yes a few minutes later Nextcloud worked again!

Tl;Dr

Go into your domains Cloudflare setting, then choose Speed and go to “Optimization”, disable the Rocket Loader™ option. Your service should start working properly again.

Getting started with RFM95W, LoRa and ESP32

In this blog post I will be introducing you to LoRa using the RFM95W module with an ESP32, so let’s get started. I also wrote a tutorial for the ESP8266.

First, we should talk about what LoRa is and what it stands for. LoRa stands for Long Range and as the name suggests one of its main aspects is its considerable range. However, we need to make a distinction between LoRa and LoRaWAN. In this tutorial, I will be talking about LoRa. LoRaWAN adds another layer of authentification. Services like TheThingsNetwork (TTN) use LoRaWAN. However, LoRa is easier to use and understand for this tutorial.

Hardware used / Preparation

For this tutorial, I will be using an RFM95W module with an ESP32. The RFM95W is our LoRa communication chip. I’ve got my ESP from the german seller AZ-Delivery (I’m not affiliated with them in any way nor do I get any money from them for mentioning their name). My RFM95W comes from Amazon.

For this, I will assume that your Arduino IDE is set up to work with ESP32s. If not here is a tutorial to do it.

Wiring

The wiring diagram

If you have a different ESP you can check the documentation supplied below for further details.

Now get started, for real

As a first step build up the setup shown above. Next, you need to install the LoRa Libary by Sandeep Mistry. More documentation is available here.

This code is actually the library’s example code modified to give a little more output.

Use the right frequencies for your region

Different regions use different frequencies for LoRa. Please check your local guidelines. Europe uses 868MHz (868E6). Update your LoRa.begin line!

#include <SPI.h>
#include <LoRa.h>

int counter = 0;
// - Pin configs -
#define ss 5
#define rst 14
#define dio0 2

void setup() {
  Serial.begin(115200);
  while (!Serial);
  delay(1000);

  Serial.println("LoRa Sender");
  // Setup LoRa transceiver module
  LoRa.setPins(ss, rst, dio0);
  
  if (!LoRa.begin(868E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }else{
    Serial.println("Starting LoRa successful");
    }
  
}

// Sends a string every 5000ms (5 seconds)
void loop() {
  Serial.print("Sending packet: ");
  Serial.println(counter);

  // send packet
  LoRa.beginPacket();
  LoRa.print("hello ");
  LoRa.print(counter);
  LoRa.endPacket();

  counter++;

  delay(5000);
}

I’ve had some issues using the code out-of-the-box. Some problems are due to the code lacking a lot of verbosity and some are due to user problems. The code above fixes one of the issues, verbosity. The other one is addressed below.

Tip

While trying to get this running I’ve run into an issue where the code returned “Starting LoRa successful”, however, no data got sent. Make sure to use the correct board, check with your manufacturer what board you should use. Different boards have different pinouts.

After changing your frequencies and making sure that you use the right board, hit the upload button. After the upload is done open your serial console, select 115200 baud. Then you should see this output:

A arduino serial output window.
The serial output

And finally, your ESP is sending LoRa. Some of the items I need for receiving are stuck in shipping this has to wait for another day. However, below is a short paragraph for those who already own an SDR.

Does this even work? For people with SDRs

This paragraph is made for people who own SDRs (SoftwareDefinedRadio). For this, I’m using a VM running ParrotOS. This image comes preinstalled with SDR++. GNUradio and a bunch of extensions for GNUradio. These extensions also contain gr-lora, which I will be using here. Following this tutorial in the wiki, you should be able to set up your workspace to receive LoRa messages. Please also remember to use the right frequency. The results looks something like this:

With this setup, I was able to use a pretty good range, even though I only used a so-called random wire antenna. This also shows how some packets are missing some data. This shows why you should always use the hash numbers to verify that the received packet is healthy. I will be talking about hashes sometime in the future.

The result as seen in SDR++

I hope I could get you on your way into the interesting world of LoRa.

OpenHAB: Zufällige Verzögerung (Jitter)

OpenHAB ist eine Quellen offene Hausautomationssoftware. In diesem Artikel erkläre ich kurz, wie es möglich ist Aktionen mit einer zufälligen Verzögerung auszuführen. Dieses Konzept nennt man auch Jitter.

Ziel

Mein Ziel ist es, ein Gerät mit einer zufälligen Verzögerung einzuschalten und dabei OpenHAB-Regeln zu nutzen. Es war von Anfang an klar, dass man den GUI Regel Editor von OpenHAB dafür nicht nutzen kann.

Die Lösung

Mit ein wenig Java-Verständnis und ein wenig lesen, kam ich auf die folgende Lösung:

rule "LampeVerzoegertAn"
when
	Time cron "0 54 20 1/1 * ? *"
then
        var int randomTime = (new java.util.Random).nextInt(20,125)
	    logInfo("org.openhab","Setting random lights timer to " + randomTime + "seconds.")
	    tRandomLights = createTimer(now.plusSeconds(randomTime)) [|
                MeineLampe.sendCommand(ON)
            ]
end

Im when-Block besagt die Zeile Time cron "0 54 20 1/1 * ? *", dass es sich um eine Zeitbasierte Regel handelt, welche um 20:54 ausgeführt wird. Das heißt, dass das Gerät frühestens um 20:54 eingeschaltet wird. In der Zeile var int randomTime = (new java.util.Random).nextInt(20,125) definieren wir die Variable randomTime des Types int (also eine Ganzzahl). In den Klammern wird der kleinste mögliche Wert (in diesem Fall 20 Sekunden) und der größte (längste) Wert angegeben(in diesem Fall 125 Sekunden, etwa zwei Minuten). Als nächsten wird eine Logausgabe erzeugt. tRandomLights = createTimer(now.plusSeconds(randomTime)) [|, erzeugt einen neuen Timer mit der Verzögerung von randomTime. Nach dem Klammerblock [| wird der passende Code eingegeben. In diesem Fall Schalte ich das Item (Aufpassen, nicht das Gerät!) ein. MeineLampe muss natürlich angepasst werden. Zuletzt wird der Block mit einer weiteren eckigen Klammer geschlossen.

Mit diesem Code habe ich erfolgreich eine Leuchte zufällig angeschaltet.

Die Geschichte um den Christian Jackson Discordserver

Wer sich jetzt fragt: “Wer ist Christian Jackson?”, hier die kurz Antwort: Ein englischsprachiger YouTuber welcher Vlogs von der Eventindustrie macht. Für alle andere geht es hier um die Geschichte um seinen Discordfanserver.

Der Anfang

Am 21.03.2020 um ca. 21:00 Uhr klicke ich den “Neuen Server erstellen”-Knopf in Discord. Hier hat alles angefangen, ich und ein paar andere haben sofort im YouTube-Livestream “Werbung” dafür gemacht, nach einiger Zeit kamen auch Leute auf den Server. Wir hatten von Anfang an mehrere Sprachkanäle (Deutsch, Englisch und später auch Niederländisch) und wollten eine offene Comunity aufbauen. Zu dem Zeitpunk hieß der Server noch “Christian Jackson Fanserver”. Wir haben Kanäle für unterschiedliche Systeme erstellt, also MA und ähnliches.

Der große Meister ist erschienen

…oder so ähnlich. An irgendeinem Nachmittag ist dann Christian Jackson auf den Server gekommen. Sehr aktiv war er aber nicht, ihm war Discord “zu komplex”. In der Zeit haben wir mehr Kanäle erstellt, damit alles seine eigenen Bereich hat und übersichtlich blieb. Das ging gut, viele fanden das Format eigentlich ganz akzeptabel, es kamen neue Leute ins Team. Es gab erste Konferenzen über den Server und der Bot wurde weiterentwickelt. Wir haben einmal die Datenbank des Bots verloren, naja Fehler passieren schonmal.

Die Ruhe vor dem Sturm

Am 31.05.2020 haben wir den Server kurz in einen “Wartungsmodus” versetzt, man konnte nur noch wenige Kanäle sehen. Zu der Zeit haben wir den Server etwas sortiert und viel ist nicht passiert. Der Server war etwa fünf Minuten nicht nutzbar.

Der 1.06.2020, war der “Doomsday”. Ich wache morgens auf, mit über 50 Nachrichten in Discord. Das heißt schonmal nichts gutes. Ohne Vorahung öffne ich Discord, eigentlich eine Fehlentscheidung. Christian (ab jetzt CJ) hatte in einen der Kanäle diese Nachricht gesendet:

Thanks for the info and ping. I don’t visit discord except maybe once a month so I’m not usually aware of these issues. I do not have the time to moderate or check in on these sort of things usually and it was my mistake to let this all happen. 

Upon reviewing what you wrote, you’ve exactly detailed what I DID NOT want to happen here. Thank you for the thoughtful and detailed message. 

This is truly my mistake for letting this operate without supervision. I don’t know anything about discord, is there a way to completely pause the server and cease all channels until this is fixed?

Und er hatte auch eine Nachricht in den Teamchannel hinterlassen:

Please make the following changes to the Discord server as soon as practicable.

Delete all bots and automation.

Delete all roles except for moderator and members. No special roles.

Delete all emotes.

No rules page that members have to agree to. Makes no sense. Anyone should be able to visit and be able to post or view the server immediately. 

Delete "Official" from the name of the server.

Any future changes must be emailed to me for approval christian@christian-jackson.com

Delete ALL channels except for the ones in the list below.  

Channels:

Lighting Design
Lighting Programming
Lighting General
Audio
Video
Other Tech
Off Topic Green Room - NSFW 18+
Off Topic Green Room - SFW All Ages
English Voice Chat
German Voice Chat
Mod/team 

Lastly, what was the comment from Josh | UK regarding explaining ways to exploit MA2 when the server was started?

Thanks.

Einer der Moderatoren hat einfach, ohne vorher mit uns zu sprechen, losgelegt. Meine erste Reaktion, war es ihm die Berechtigungen weg zu nehmen, als “Schadensbegrenzung”. Wir waren alle sehr angefressen. Warum? Nun ja, er kam einfach aus dem Nichts und hat Änderungen gefordert, nachdem er uns vermittelt hatte, dass er mit der Serverleitung nichts zu tun haben möchte. Wirklich gut fanden wir das natürlich nicht. An diesem Punkt war es fast schon zuspät wegen dem bereits genannten Moderator. Wir haben einen zwei Seiten langen “Brief” an ihn geschrieben, das wir das nicht gut finden. Wir haben nach einigen Tagen eine etwas sehr kurze Antwort bekommen. Diese klang etwas so: “Ihr habt Pech gehabt. Euer Problem.” So war das nicht gemeint, wurde aber so aufgefasst.

Und jetzt?

Der Server ist reduziert auf wenige Kanäle und ein Admin unseres Teams ist gegangen und der Moderator von zuvor wurde “entlassen”. Auf dem Bild hier drunter sieht man auch mal die Admin und Teambereiche. Am 6.6.2020 habe ich dann final das Team verlassen. Am 11.6.2020 gab es noch eine lange Diskussion um das ganze Thema im “off-topic-sfw-all-ages”-Channel.

Der aktuelle Zustand.

Wie es weiter geht weiß niemand. Ich werde diesen Artikel versuchen aktuell zu halten. Der englische Artikel ist meistens aktuelller.

« Older posts

© 2024 Thegreydiamond

Theme by Anders NorenUp ↑