Jump to content

Eric The Tech Guru

Member
  • Posts

    219
  • Joined

  • Last visited

Awards

2 Followers

Contact Methods

Profile Information

  • Gender
    Male
  • Location
    San Francisco
  • Interests
    Photography, learning new things, software engineering, hardware projects, music, computers.
  • Occupation
    Software Engineer

System

  • CPU
    AMD Ryzen Threadripper 1950X
  • Motherboard
    Asus x399 Prime-A
  • RAM
    4x8GB Crucial Ballistix Sport 2400Mhz DDR4
  • GPU
    Nvidia GTX 1080ti SC2 (EVGA)
  • Case
    CoolerMaster MasterCase 5 Pro
  • Storage
    1 x 1TB Samsung 960 Evo NVME SSD, 1 x 512GB Samsung 950 Pro NVME SSD, 1 x 1TB Samsung 850 Evo, 2x 250GB Samsung 850 Evo, 2x 3TB Western Digital Caviar Green
  • PSU
    Corsair RMX 850 White Edition
  • Display(s)
    1 x Acer Predator X34, 1 x LG 31MU97-B
  • Cooling
    Noctua NH-U14S TR4-SP3 Edition
  • Keyboard
    WASD V2 10 Keyless Custom MX Cherry Green
  • Mouse
    Logitech G703
  • Sound
    Focusrite 2i2 + 2x M-Audio BX5 and AKG K7XX Massdrop Edition
  • Operating System
    Windows 10 Pro / Linux Mint
  • PCPartPicker URL

Recent Profile Visitors

1,831 profile views
  1. That circular PCB looked similar to an OtterCast in form-factor, can only dream that it might be a Chromecast Audio replacement like that. Actually, after looking at it a bit more it looks like it has a place for a LiPo battery or something, likely not an OtterCast then but something that's supposed to be portable and puck-shaped.
  2. Given we see the tilde (~) inside the brackets there, I'm assuming that's where we'd see the current directory which appears to be the root user's home directory in the video.
  3. How SREs Solve Problems at Home (Making my Dumb Fridge Smart) 07 Mar 2021 Pretext This is a story partially about laziness but the weird kind of laziness where, instead of doing the thing, you decide to do something completely different and more convoluted that ends up taking way more time because you can’t be bothered to do the thing. In this instance, the thing is fixing my fridge (though I would argue it shouldn’t be my responsibility to do that, I rent and my landlord should have fixed this when it became an issue months ago but oh well). My Fridge is Broken My fridge, being manufactured in 2003, is old enough to vote. I learned that my fridge was broken by opening the attached freezer on top and looking at a puddle in my ice bin. While this was a useful signal to notice something was wrong with my fridge, I didn’t know what was wrong or how I could fix it. Chatting with my landlord, he mentioned “the previous tenant had a similar issue and whenever it happened, they would cut power to the fridge and wait about 15 minutes and then turn it back on”. For context, the freezer and fridge share a compressor in models like this: Well, at least now I had a remediation step to take, so I gave it a shot and don’t you know, it worked perfectly! Problem solved! …Not really though, unless I want to be checking on my ice bin hourly to know if I needed to power cycle it, I needed another solution. At this point a normal person might consider trying to repair the fridge or hiring someone to do as much, but it’s been over a month since the fridge technician made his house call and there has been no follow-up while the issue persists. So I hopped on amazon and started to solve the problem the only way I know how: with metrics and automated remediation! The Metric For this problem, there are several metrics we could consider. Initially, my metric was looking in the ice bin to see if it was melting (if it was, this would lead to it all refreezing once the compressor started up again turning my cubes into a giant chunk of ice). While this metric works well for me (a human) it also catches the problem too late (the ice has already begun to melt meaning the freezer is over 32F) and it is harder to measure with a computer (maybe a trained computer vision model could learn to see melting ice differently from non-melting ice but that’s a bit more than I signed up for). The solution I settled upon was to monitor the temperature inside the freezer with a bluetooth thermometer probe (though another way could be something like monitoring power draw at the wall of the fridge). I picked up the cheap bluetooth thermometer here for around $15 and set to work installing the app and checking it regularly. This let me observe temperatures that the freezer oscillates between during normal operation and what it looks like when the temperature begins to run away: As you can see, the temperature sits somewhere from 2.5F to 12F regularly and occasionally spikes during weird events. Clearly in the image shown the spike was halted by the system I’m about to build in this blog. So we have a metric and graph viewable in an app. Let’s grab some random FOSS project that can talk to these weird thermometers over bluetooth and slap in in a Raspberry Pi. Gathering Data To interface with the thermometer, instead of using the weird limited app I wondered if someone else had taken a crack at talking to this device directly and it turns out they did! I found a project called Inkbird and forked it to twist to my nefarious purposes of making my fridge smart. In a nutshell, this is a node.js project that utilizes the noble BLE module to talk to Inkbird thermometers. Though this code was written for a previous version, so I had to modify one of the constants to scan BLE devices and filter for the correct device name. I found the right name through experimenting with a bluetooth scanning app on my phone and opening and closing the freezer door to see which device jumped in signal when it opened. I wrote a loop that connects to the thermometer once a minute to avoid killing its battery prematurely. It grabs one datapoint containing a temperature and battery level reading and then disconnects. It then exposes the program state via a JSON API endpoint with Express. An abbreviated form of the final product can be found below: const IBS_TH1 = require("./ibs_th1"); const log4js = require("log4js"); const logger_ = log4js.getLogger(); logger_.level = "info"; const device = new IBS_TH1(); let state = { connecting: false, gotData: false, waitCount: 60, //... }; let sensorState = { temps: [], battery: 0, lastUpdated: new Date().toString("en-US"), }; const callback = (data) => { logger_.debug( `Current Temp: ${data.temperature.toFixed(2)}°F -` + ` Battery: ${data.battery}%` ); sensorState.battery = data.battery; if (sensorState.temps.length > 60) { sensorState.temps.shift(); } sensorState.temps.push(data.temperature.toFixed(3)); sensorState.lastUpdated = new Date().toString("en-US"); state.gotData = true; device.unsubscribeRealtimeData(); logger_.debug("Disconnecting from sensor"); }; const dutyLoop = function () { //... if (!state.connecting && state.waitCount >= 60) { device.subscribeRealtimeData(callback); logger_.debug("Connecting to sensor"); state.connecting = true; } else if (!state.connecting) { state.waitCount++; } else { if (state.gotData) { state.gotData = false; state.waitCount = 0; state.connecting = false; } } }; logger_.info("Starting duty loop..."); setInterval(dutyLoop, 1000); Metric Monitoring and Heuristics This code as written will build a running log of the past 60 minutes of one-per-minute measurements of freezer temperature, and track the current battery life of the sensor. To enhance it we want to add some kind of heuristic to determine if the freezer is too warm. We can do that by setting a trigger temperature and then a number of minutes the freezer must be above that temperature to trigger the alarm. We also want to add an alarm cooldown so we don’t trigger once a minute while the freezer temp is rising. Since even if we kick in remediation it can take some time to drop the temps back down. So we’ll add these variables to state: let state = { //... triggerTemp: 20, triggerMinutes: 5, lastPowerReset: new Date(0), cooldownMin: 60, powerCycleWaitTime: 15, } Nice, now we want to add the heuristic to our loop by grabbing the last triggerMinutes worth of measurements from sensorState.temps and checking if all of them are over the triggerTemp. const dutyLoop = function(){ // Evaluate state const now = new Date(); if (now - state.lastPowerReset > state.cooldownMin * 60000) { if ( sensorState.temps .slice(-state.triggerMinutes) .filter((temp) => temp > state.triggerTemp).length >= state.triggerMinutes ) { logger_.info( `Freezer has been over trigger temp of (${state.triggerTemp}F) for at least (${state.triggerMinutes}) minutes.` ); if (now - state.lastPowerReset > state.triggerMinutes * 60000) { logger_.info( `Resetting fridge power, last reset was at (${state.lastPowerReset.toLocaleString( "en-US" )})` ); state.lastPowerReset = now; // Remediate the problem... } } } //... } Finally, we need to somehow remediate the problem. Automated Remediation We know that powering the fridge off and waiting about 15 minutes and turning it back on seems to remediate the issue. Do I know why that works? No. Do I need to know in order to fix it? Also no. But we can simply automate the power cycling to make this problem fix itself. All I need to do is power off the fridge, wait 15 minutes, and turn it on, but from code. As a bit of background I wrote this home automation API in Go a couple months ago which talks to Philips Hue, Belkin WeMo, and Tasmota IOT devices through different protocols and gives me the ability to control them at will and with automation. The interesting bits for this project are the SetStateHandler which can be found here. This code allows me to set the power state of a given Tasmota outlet connected to a MQTT broker in my apartment. I hacked up some old Gosund ESP8266 based WiFi Smart Plugs and installed Tasmota on them with the aid of TuyaConvert which allows you to OverTheAir upgrade some off-the-shelf IOT devices. It is worth knowing that some of the recent Gosund units I’ve bought from Amazon have updated firmware that is harder to flash and until recently I wasn’t able to update them until the TuyaConvert project managed to crack some of their newer security features for OTA updates. So we have an API in my home that allows me to talk to an outlet and make it turn on and off, so the last thing to do is integrate it into the temperature tracking code. We’ll use Axios to make a JSON POST request to the API as required. const axios = require("axios"); const setFridgeState = function (desiredState) { axios .post(process.env.OUTLET_URL, { apiKey: process.env.OUTLET_API_KEY, device: process.env.OUTLET_DEVICE_NAME, powerState: desiredState, }) .then((res) => { logger_.info( `Successfully set fridge to state (${desiredState}): `, res.data ); }) .catch((err) => { logger_.error(`Failed to set fridge to state (${desiredState}): `, err); }); }; Now we can invoke the setFridgeState function from our heuristic code to turn off the fridge and use the powerCycleWaitTime variable to tell it how long to wait before turning the fridge back on. const dutyLoop = function(){ //... // Remediate the problem... state.lastPowerReset = now; setFridgeState("off"); setTimeout(() => { logger_.info( `Powering fridge back on after (${state.powerCycleWaitTime}) minutes...` ); setFridgeState("on"); }, state.powerCycleWaitTime * 60000); //... } Conclusion We now have a system that detects when the metric is over a threshold for a specified period of time, triggers a remediation step to bring the metric back under the threshold, and then cools down before trying to remediate again. Or in normal terms: if the freezer is getting too warm we turn the fridge off and wait 15 minutes and turn it back on. But we don’t try this more than once in an hour to let the compressor do its work. The full source code can be found here, but I hope nobody is in a situation where you have to use it. This was a fun project that let me use tools from the SRE toolbox to solve an everyday problem and the best part is that it actually works! The compressor didn’t turn on last night around 1:30 AM and the system recognized it before the freezer got to 30F and corrected it without any weird bugs! I now no longer have to worry about food spoiling in the fridge overnight because the fridge forgot to cool things. One more thing I might consider adding to the system is a notification to my email when a remediation attempt is made so I can see if this problem is getting worse or if there might be an issue with the code if it tries to remediate at high frequency. Please note that all of this code for this project is really just duct taped together to fix my fridge and not representative of the code I typically write on “important” projects. The gohome code is a bit more polished so go look at that instead. The total Bill of Materials for the project was around $50 including one Gosund outlet, one Raspberry Pi 3B+, and one Inkbird IBS-TH2. That’s all folks, thanks for reading. Eric V Note: The contents of this post are from my blog and have been copied to fit this forum page.
  4. I mean this is how floaplane started, with a shoddy ffmpeg driver written in Node.JS that would fire off transcoding jobs after file uploads to a CMS. Eventually the CMS just sent items into a work queue and render nodes picked jobs off the queue to process them.
  5. So what Luke was talking about is likely BCrypt which is a very secure and awesome hashing function that uses the Blowfish cipher as part of the hashing process. Blowfish has a maximum key size of 448 bits (or 56 bytes), though in the bcrypt algorithm, it processes things with 18 x 32-bit subkeys (which comes out to 72 bytes total, so 71 bytes not including terminator at the end of the string). However if we take UTF-8 into consideration, any UTF-8 string that exceeds 72 bytes is truncated to 72 bytes, so some UTF-8 characters exceed that on their own. The real solution is to pre-hash passwords using something like SHA-256 and then passing the SHA-256 hash (which are fixed to 45 characters including null) into the bcrypt algorithm, which will allow arbitrarily long passwords (though you might want to limit it to 1024 or something to prevent annoying DOS through password submission). There's a really good writeup on it on security stackexchange here - https://security.stackexchange.com/a/184090
  6. I misunderstood your comment and wrote a response then deleted it.
  7. Does your laptop have something like Realtek audio manager installed? There's usually a "microphone level" slider somewhere in that application that can be dragged to 1% fairly easily by accident. Also check your windows sound devices input levels. See: https://answers.microsoft.com/en-us/windows/forum/all/boost-mic-volume/34d53038-34a3-4138-99dc-6d994bb57840
  8. Tickets aren't finalized yet, even prices and ticket tiers haven't been worked out between LMG and Dreamhack. It probably won't be until February for ticket prices to be announced, keep tuning into WAN show for news and watch the LTX blog on the LTX website.
  9. I'm a third year in university and will be flying in from work in SF for LTX this summer. It'll be my first time there but I've been meaning to hang out with some LMG people since floatplane stuff started, just never managed to get up to Vancouver cause school...
  10. Elon is still CEO just no Chairman of the board. He doesn't get to direct the company as much but he gets to decide how to execute on the board's direction.
  11. Even in the Tesla case it's a very minor punishment with no admission of guilt on Musk or Tesla's side. Musk remains the CEO, he just loses some of the decision making powers he probably shouldn't have had in the first place. A slap on the wrist or even less than that. Equifax is worth like around $16 Billion, it also doesn't have any other serious competitors besides TransUnion and if the SEC did anything to seriously hurt Equifax, it would turn the credit market into a virtual monopoly.
  12. Yeah, Tesla is right behind GM in market cap, second largest US based and US owned auto manufacturer.
  13. The funniest part was if he had set the price to $419 they probably would have let him off the hook. The markup of 20% from TSLA's closing price the day before he tweeted (which he said was his reason for the pricing tweet) would have been $419 by the SEC's calculations but he bumped it to 420 for the meme.
×