Your VEVOR 7-in-1 Wi-Fi Weather Station YT60234 in Weewx

This write-up could easily be entitled The Rise and Fall of my FT0310 weather station, but to appease the Gods of SEO, I’ll focus on the weewx angle.

The Decline

As you may have guessed, my FT0310 weather station written up here has bitten the dust after a little over two years in operation. A few weeks ago the console stopped displaying illumination and UV data because the external sensor unit began sending what I assume is error code data (insanely high lux and UV values). A cursory check showed water droplets on the inside of the light sensor hatch, so I assumed that something wasn’t waterproofed sufficiently.

Interestingly, after doing a post-mortem, I found a family of spiders happily living inside my sensor unit. Although there was some moisture on the UV sensor board, there is no evident damage. Visual inspection provided no clues as to why both the UV and the temperature/humidity boards have failed, but the investigation is still ongoing.

I also correctly assumed the possibility of a cascade failure and immediately did some light research and ordered a replacement/backup unit, namely the VEVOR 7-in-1 Wi-Fi Weather Station, YT60234, produced by Youtong.

A few weeks later the console stopped displaying humidity and temperature data, thus expediting the replacement.

This part was fairly easy, I just reused my Weathercloud and Weather Underground station ID’s on the new station and got it running in less than half an hour, since its firmware and WIFI support rely on a similar backend.

YT60234 Vevor 7-in-1 weather station in Weewx

To get its data into Weewx, I had to do the following:

  1. Change the RTL_433 run command in sdr.py plugin to listen on the correct frequency, which is 868.3 MHz, thus something along the lines of rtl_433 -M utc -F json -f 868.3M. This is the frequency you’d also use when troubleshooting.
  2. Add a new entry for the station in sdr.py. Please note that this station provides wind speed in km/h so convert values accordingly if necessary. I’ve included a function to convert km/h to m/s in case you need it.
    class Vevor7in1Packet(Packet):
    # {"time" : "2024-11-13 13:27:59", "model" : "Vevor-7in1", "id" : 52266, "channel" : 0, "battery_ok" : 1, "temperature_C" : 5.400, "humidity" : 76, "wind_avg_km_h" : 0.700, "wind_max_km_h" : 2.667, "wind_dir_deg" : 87, "rain_mm" : 12.116, "uv" : 0, "light_lux" : 7213, "mic" : "CHECKSUM"}'
    IDENTIFIER = "Vevor-7in1"

    @staticmethod
    def parse_json(obj):
    pkt = dict()
    pkt['dateTime'] = Packet.parse_time(obj.get('time'))
    pkt['usUnits'] = weewx.METRICWX
    station_id = Packet.get_int(obj, 'id')
    pkt['battery'] = Packet.get_int(obj, 'battery_ok')
    pkt['temperature'] = Packet.get_float(obj, 'temperature_C')
    pkt['humidity'] = Packet.get_float(obj, 'humidity')
    pkt['wind_gust'] = kmh_to_ms(Packet.get_float(obj, 'wind_max_km_h'))
    pkt['wind_speed'] = kmh_to_ms(Packet.get_float(obj, 'wind_avg_km_h'))
    pkt['wind_dir'] = Packet.get_float(obj, 'wind_dir_deg')
    pkt['total_rain'] = Packet.get_float(obj, 'rain_mm')
    pkt['light_lux'] = Packet.get_int(obj, 'light_lux')
    pkt['uv'] = Packet.get_float(obj, 'uv')
    pkt = Packet.add_identifiers(pkt, station_id, Vevor7in1Packet.__name__)
    return pkt

    def kmh_to_ms(v):
    if v is not None:
    v /= 3.6
    return v
  3. map the sdr.py data in weewx.conf (52266 is my unique station ID, yours will probably be different).
    [[sensor_map]]
    windDir = wind_dir.52266.Vevor7in1Packet
    windSpeed = wind_speed.52266.Vevor7in1Packet
    windGust = wind_gust.52266.Vevor7in1Packet
    outTemp = temperature.52266.Vevor7in1Packet
    outHumidity = humidity.52266.Vevor7in1Packet
    rain_total = total_rain.52266.Vevor7in1Packet
    UV = uv.52266.Vevor7in1Packet
    luminosity = light_lux.52266.Vevor7in1Packet

If any of the above instructions are unclear, make sure to check out my original post, because it contains more information.

WLED Balcony Display

Here’s a fun little project I’ve set up for the holidays. (Work in progress!)

I’ve been dabbling with the wonderful world of individally-addressable LEDs for a while and use them in all sorts of setups, but what got me really interested are the 5V-powered “fairy pixel” flexible LED strips, handy because they’re easily powered from a power bank. The first version I ordered came with a controller which, although it worked fairly well, did not allow for advanced configuration and some more complicated setups.

It took me a whole week of tinkering with it before I re-used the LED strip on a ESP8266 controller flashed with WLED, mounted it on two cable ducts and turned it into a 160 cm x 92 cm portable LED matrix with a resolution of 20 x 10 pixels.

The layout

Since my balcony has a transparent (albeit opaque) glass balustrade, I figured I would simply stick a LED matrix behind it and turn it into a large LED screen.

First trials with the portable LED matrix looked good enough, but I wanted more resolution.

My balustrade consists of two 129 x 89 cm glass panes, so after a bit of calculation I opted for two 20-metre LED fairy pixel strings of 400 LEDs each (spaced 50 mm apart), one for each pane, in a vertical serpentine pattern to avoid any need to rearrange, cut or solder the strip. In one piece, the whole setup is also removable post-holiday season, as I’m not certain how well the LED strip would survive the scorching heat and exposure to strong sunlight.

For my glass pane height, I could have easily fit 18 LEDs per column which would give me the effective resolution of 22 x 18 pixels plus a few to spare. Unfortunately, this would also mean that if the columns were spaced according to their spacing of 50 mm, which would drop to about 40 mm since the LEDs have to be rotated to face the glass pane, 22 columns x 40 mm would actually cover a 90 x 83 cm area on a 129 x 89 pane.

To overcome this, I opted to “sacrifice” the 18th led of each column, which gave me flexibility in spreading out the columns without cutting the strip. By arranging the columns 55 mm apart, the LED matrix would cover a rectangle of 120 x 83 cm on a 129 x 89 pane, which was much better.

In order to easily space the LEDs apart, I’ve designed and 3D-printed holders and spacers.

Top and bottom holders serve multiple purposes:
1. they keep the LEDs facing outwards towards the glass, because I need them to shine through the glass to be visible through the opaque pane. They shine quite brightly enough to be clearly visible from the inside.
2. they keep the led string taut and secure on the glass without the need to glue or fasten them in some other way.
3. they keep my LED string removable. At some point I can just remove the LED string and leave the holders in place all year round.

The height and the width of the holders was calculated so that they hold the strip firmly in place, also providing sufficient surface area for adhesion to the surface. I used transparent double-sided “nano tape” to stick them to the glass.

Spacers are a bit smaller than the holders and only serve to keep LED columns properly spaced and facing the glass. They can be stuck to the glass if necessary, but work quite well without any tape.

3D print models for the case and holders (Fusion360 and 3mf) can be found here.

The controller and wiring

WLED will be handling 800 LEDs at a time, so I’ve opted for an ESP32 controller, with each 400-LED string on a separate GPIO.  To make the thing easily replaceable, the controller is on a proto-board in a 3D printed case with a DC-jack for power and two 3,5 mm stereo jacks to make the LED strips easily detachable.

The thin fairy-pixel wire has huge voltage drops due to its length of 20 metres, so although a strip can be connected to the controller at one end, it cannot be powered directly from the ESP32 pin, meaning you have to power them directly from the PSU on both ends. Even powered that way, the voltage drop is visible at higher brightness levels and LED colours that require all three LEDS (for example white), so make sure you limit the current in WLED to make this less noticeable. The whole thing is powered by a 5V, 10A PSU. I’ve decided to put the controller in the middle, between both strips, so as to avoid the need to run a separate data line. This way I only need a two-wire power line covering the entire span of the LEDS.

WLED configuration

Ironically, this part of the whole affair took a lot of time to get right, so I suggest you learn from my mistakes. After a few hours trying to get various AI models to work out how to configure the matrix panel with ‘skipped’ LEDs and failing miserably, the WLED jsonmap generator proved very helpful, although not perfect for my purposes. Good old spreadsheet with its sequential cell autocompletion to the rescue!

As I mentioned, each strip is on a different GPIO, so under LED preferences I have both strips configured identically on different pins. This means that leds 0-399 will be the right panel, while leds 400-799 will be the left panel.

Keeping in mind that I have ‘skipped’ pixels and extra LEDs that won’t ever be used, I’ve created this spreadsheet to make things easier.

As you can see, it’s a serpentine pattern, starting in the middle – three skipped LED’s, followed by a downward-facing spacer LED, followed by 17 pixels and ending with an upward-facing spacer LED. The pattern continues for a total of 22 columns to the right. The left one is mirrored. LEDs don’t start at zero because there are extras which I’ve left at the beginning and end to avoid having to extend the cable.

Also note that I have numbered the ‘sacrificed’ upward and downward facing LEDs which I’ll be able to use independently of the 2D matrix as two 1D strips (top and bottom).

I’ve done this in a spreadsheet so I can just copy the array layout LED order into a ledmap.json file, which I then uploaded to http://wled/edit.

More on the WLED ledmap.json

According to the WLED jsonmap generator, the correct format for a ledmap.json file for a 2D matrix is as follows:

{"n":"my_matrix","width":16,"height":5,"map":[
0,9,10,19,20,29,30,39,40,49,50,59,60,69,70,79,
1,8,11,18,21,28,31,38,41,48,51,58,61,68,71,78,
2,7,12,17,22,27,32,37,42,47,52,57,62,67,72,77,
3,6,13,16,23,26,33,36,43,46,53,56,63,66,73,76,
4,5,14,15,24,25,34,35,44,45,54,55,64,65,74,75
]}

The array has to be defined in size and the LEDs, regardless of the order, have to be defined as an array. If any LEDs aren’t supposed to be a part of the matrix, you just skip them and leave them for later. I’ve copied the matrix part of my spreadsheet, comma-separated, without any added spaces because WLED doesn’t tolerate them. If you don’t define a matrix in ledmap.json and instead just shuffle the order of LEDs and try to define a matrix through the 2D settings, the 2D matrix will not work! 

The great part about ledmap.json is that, after you’ve defined your main matrix, you can reshuffle and renumber any leftover LEDs to use them as a 1D strip. So I’ve added my top and bottom strips, omitting only the unneeded LEDs. My final ledmap.json is as follows – please note that comments are unsupported, I’ve included them in the code block to better explain what is what.

{"n":"2DMatrix","width":44,"height":17,"map":[
//first row of my 44x17 matrix 781,779,745,743,709,707,673,671,637,635,601,599,565,563,529,527,493,491,457,455,421,419,21,23,57,59,93,95,129,131,165,167,201,203,237,239,273,275,309,311,345,347,381,383,
//
// rows omitted
//
// final row of the matrix
797,763,761,727,725,691,689,655,653,619,617,583,581,547,545,511,509,475,473,439,437,403,5,39,41,75,77,111,113,147,149,183,185,219,221,255,257,291,293,327,329,363,365,399,
// 1D strip begins here - upwards-facing LEDs - top row
780,744,708,672,636,600,564,528,492,456,420,22,58,94,130,166,202,238,274,310,346,382,
// downwards-facing LEDs - bottom row
798,762,726,690,654,618,582,546,510,474,438,402,4,40,76,112,148,184,220,256,292,328,364]
}

WLED segment configuration

In order to be able to control the 2D matrix and the top/bottom strips independently, the segments in WLED need to be individually configured.

First I defined a 44×17 2D panel in Config > 2D configuration. This created a corresponding 2D segment using the first 748 LEDs, which are zero-indexed, so LEDs 0-747.

After that, I added two separate 1D segments, “Top” starts at LED 748 and ends at 770, “Bottom” starts at 770 and ends at 793 (yes, this strip has one LED more than the top one).

I’ll update this post with more information. For now, here’s a demo.

Bill of materials

  • ESP32 mini prototype board (under 4 €)
  • “20M400LEDs WS2812B LED String Dreamcolor Christmas Lights” AKA “fairy pixel LED strip” without a controller (around 18 € per 20 m at the time of writing, cheaper 3-wire version is sufficient for a serpentine layout)
  •  5V 10A PSU + box if needed
  • 3.5mm 3-pole (stereo) plug + socket (2 pcs)
  • 12V Male + Female Connectors 2.1*5.5mm (3 pairs)
  • Nano tape (dual sided transparent adhesive tape)
  • cables and wires as needed