#AzureIoT – Using a Raspberry Pi Grove Sensor in an ☁ Azure IoT Edge Module (4/N)

Buy Me A Coffee

Hi !

In my previous post I the steps to create an Azure IoT Module interacting with Grove sensors in a Raspberry Pi. I won’t write about Azure Container Registry, check the references section for more information. At this point I’ll azure we have an ARM32 image is published and ready to use from an ACR.

On Azure IoT on the module, let’s go to the [Set Modules] section and add the ACR information: name, address, user name and password. Then we can add a new module with the [Add // IoT Edge Module] option

Let’s define the name for the module, just in case, I always do this in lowercase. And then the uri which usually uses the format

# template
<your ACR>.azurecr.io/<module name>:<image version>-arm32v7

# in example for ebgrovetemperaturedht11 - version 0.0.43
[<your ACR>.azurecr.io/ebgrovetemperaturedht11:0.0.43-arm32v7]
add new custom module

As I wrote in my previous post, the module uses Environment Variables, so we can define them here

azure iot module define environmental variables

And, finally as I mentioned before, the specific create options to allow access to the grove sensors.

Confirm and Create the module with these options, and 20 seconds later we can see this module up and running in the Edge device,

azure iot modules up and running

And that’s it! I may add some extra posts with some specific details, however I hope that these 4 posts may help someone starting in a similar scenario!


Happy coding!


El Bruno

¿Con ganas de ponerte al día?

En Lemoncode te ofrecemos formación online impartida por profesionales que se baten el cobre en consultoría:

#AzureIoT – Using a Raspberry Pi Grove Sensor in an ☁ Azure IoT Edge Module (3/N)

Buy Me A Coffee

Hi !

In my previous post I shared a Python script that reads value from a Grove sensor and send the values as device telemetry to Azure IoT Hub. In today’s post I’ll share some insights and lessons learned on how to pack this as an Azure IoT Module.

In the references section I shared a Microsoft Docs tutorial on how to create a Azure IoT Module. That article cover the core steps to create the module using Visual Studio Code. I’ll focus on the main changes that we need to perform to make the module work.

Module Code

The module code is similar to the previous posts. The main difference will be around how the code and threads are managed. Based on the Azure IoT Python template, I’m using asyncio to work with threads. Another change is that, in this scenario, the interval timer will be defined as an environmental variable in the module definition.

# Copyright (c) Bruno Capuano. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
# Using the Python Device SDK for IoT Hub:
# https://github.com/Azure/azure-iot-sdk-python
# Azure IoT dependencies installed with >> pip install azure-iot-device
# read temp and humi from DHT11 Sensor
# read values are triggered device message with the information.
import time
import os
import sys
import asyncio
import seeed_dht
from six.moves import input
import threading
from azure.iot.device.aio import IoTHubModuleClient
from azure.iot.device import IoTHubDeviceClient, Message
from AzureIoTLogger import AzureIoTLogger
from AzureIoTEnvironment import AzureIoTEnvironment
trigger_enabled = False
refresh_interval = 5
MSG_TXT = '{{"temperature": {temperature},"humidity": {humidity}}}'
sensor = None
log = None
def twin_patch_handler(patch):
AzureIoTLogger.Log("the data in the desired properties patch was: {}".format(patch))
async def main():
global refresh_interval, sensor, module_client, log
if not sys.version >= "3.5.3":
raise Exception( "The sample requires python 3.5.3+. Current version of Python: %s" % sys.version )
# The client object is used to interact with your Azure IoT hub.
module_client = IoTHubModuleClient.create_from_edge_environment()
AzureIoTLogger.Log("IoT Hub Client for Python OK" )
# read environmental vars
trigger_enabled = AzureIoTEnvironment.GetEnvVarBool('ReportValues')
refresh_interval = AzureIoTEnvironment.GetEnvVarInt('Interval')
# connect the client.
await module_client.connect()
AzureIoTLogger.Log("Azure IoT client connected OK" )
# set the twin patch handler on the client
module_client.on_twin_desired_properties_patch_received = twin_patch_handler
# init sensor
sensor = seeed_dht.DHT("11", 12)
AzureIoTLogger.Log("Temp/Humi sensor OK" )
while True:
humi, temp = sensor.read()
if not humi is None:
AzureIoTLogger.Log('DHT{0}, humidity {1:.1f}%, temperature {2:.1f}*'.format(sensor.dht_type, humi, temp))
AzureIoTLogger.Log('DHT{0}, humidity & temperature: {1}'.format(sensor.dht_type, temp))
if (trigger_enabled == True):
msg_txt_formatted = MSG_TXT.format(temperature=temp, humidity=humi)
message = Message(msg_txt_formatted)
message.custom_properties["temperature"] = temp
message.custom_properties["humidity"] = humi
await module_client.send_message(message)
except Exception as e:
AzureIoTLogger.Log("stdin_listener exception.", e)
# Cancel listening
# Finally, disconnect
await module_client.disconnect()
except Exception as e:
AzureIoTLogger.Log ( "Unexpected error %s " % e )
if __name__ == "__main__":

Docker Permission to grant low level hardware access

Our module will interact with GPIO, so when we define and create the module for our device, in the Container Create Options, we need to add the following lines:

  "HostConfig": {
    "Privileged": true

Enabling access to the i2c and also running the module with elevated privileges:

Install Grove dependencies on the Docker Image

This one took me some try & test & fail & learn until I figure it out. So, we need to add this dependencies in the requirements.txt file:


However, when I build the image remotely in my device I got the following error

    Running setup.py install for RPi.GPIO: started
    Running setup.py install for RPi.GPIO: finished with status 'error'
    ERROR: Command errored out with exit status 1:
     command: /usr/local/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-zxn0f5l4/rpi-gpio_20705074d6cc4e37b7794843814bcb85/setup.py'"'"'; __file__='"'"'/tmp/pip-install-zxn0f5l4/rpi-gpio_20705074d6cc4e37b7794843814bcb85/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-4mka4lwh/install-record.txt --single-version-externally-managed --compile --install-headers /usr/local/include/python3.7m/RPi.GPIO
         cwd: /tmp/pip-install-zxn0f5l4/rpi-gpio_20705074d6cc4e37b7794843814bcb85/
    Complete output (16 lines):
    running install
    running build
    running build_py
    creating build
    creating build/lib.linux-armv7l-3.7
    creating build/lib.linux-armv7l-3.7/RPi
    copying RPi/__init__.py -> build/lib.linux-armv7l-3.7/RPi
    creating build/lib.linux-armv7l-3.7/RPi/GPIO
    copying RPi/GPIO/__init__.py -> build/lib.linux-armv7l-3.7/RPi/GPIO
    running build_ext
    building 'RPi._GPIO' extension
    creating build/temp.linux-armv7l-3.7
    creating build/temp.linux-armv7l-3.7/source
    gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/usr/local/include/python3.7m -c source/py_gpio.c -o build/temp.linux-armv7l-3.7/source/py_gpio.o
    unable to execute 'gcc': No such file or directory
    error: command 'gcc' failed with exit status 1
ERROR: Command errored out with exit status 1: /usr/local/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-zxn0f5l4/rpi-gpio_20705074d6cc4e37b7794843814bcb85/setup.py'"'"'; __file__='"'"'/tmp/pip-install-zxn0f5l4/rpi-gpio_20705074d6cc4e37b7794843814bcb85/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-4mka4lwh/install-record.txt --single-version-externally-managed --compile --install-headers /usr/local/include/python3.7m/RPi.GPIO Check the logs for full command output.
The command '/bin/sh -c pip install -r requirements.txt' returned a non-zero code: 1

As I mentioned, this took me some time until I figure out the right dependencies, and at the end I added 2 changes to my docker to make it work. I updated the [Dockerfile.arm32v7] and end it with these content

FROM arm32v7/python:3.7-slim-buster


# custom installation for RPI Grove dependencies defined in requirements.txt
RUN apt-get update 
RUN apt-get install -y gcc

COPY requirements.txt ./
RUN pip install -r requirements.txt

COPY . .

CMD [ "python3", "-u", "./main.py" ]

Full module source is available here https://github.com/elbruno/Blog/tree/main/20210308%20AzureIoT%20Module%20Rpi%20Grove%20Temp/ebGroveTemperatureDht11

In tomorrow post, I’ll share the final steps to have the module up and running with Azure IoT.


Happy coding!


El Bruno

¿Con ganas de ponerte al día?

En Lemoncode te ofrecemos formación online impartida por profesionales que se baten el cobre en consultoría:

#RaspberryPi – Build #docker 🐳 images from Visual Studio @Code remotely using a Raspberry Pi. #AzureIoT

Buy Me A Coffee

Hi !

The post title is very descriptive, however let me share some more context on why I needed this scenario.

I’m currently working in an Azure IoT custom module. I got installed the Azure IoT extensions on Visual Studio Code, so everything works great on the Hello World mode. Once I wrote my code logic in C#, I can easily build my IoT Edge Solution.

My default configuration focus to an amd64 platform. I got this defined in my settings.json

    "azure-iot-edge.defaultPlatform": {
        "platform": "amd64",
        "alias": null

This is a sample log output, using my local docker in Windows 10. Everything works fine.

[+] Building 0.7s (16/16) FINISHED
 => [internal] load build definition from Dockerfile.amd64                                                                                                                                                                                  0.1s
 => => transferring dockerfile: 38B                                                                                                                                                                                                         0.1s 
 => [internal] load .dockerignore                                                                                                                                                                                                           0.1s 
 => => transferring context: 34B                                                                                                                                                                                                            0.1s 
 => [internal] load metadata for mcr.microsoft.com/dotnet/core/runtime:3.1-buster-slim                                                                                                                                                      0.5s
 => [internal] load metadata for mcr.microsoft.com/dotnet/core/sdk:3.1-buster                                                                                                                                                               0.5s 
 => [build-env 1/6] FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster@sha256:0fece15a102530aa2dad9d247bc0d05db6790917696377fc56a8465604ef1aff                                                                                               0.0s
 => [internal] load build context                                                                                                                                                                                                           0.0s 
 => => transferring context: 446B                                                                                                                                                                                                           0.0s 
 => [stage-1 1/4] FROM mcr.microsoft.com/dotnet/core/runtime:3.1-buster-slim@sha256:e84300e54209cad66611b0b483cfe8c007d3bb5450388ff58e7f15d025917817                                                                                        0.0s 
 => CACHED [stage-1 2/4] WORKDIR /app                                                                                                                                                                                                       0.0s
 => CACHED [build-env 2/6] WORKDIR /app                                                                                                                                                                                                     0.0s 
 => CACHED [build-env 3/6] COPY *.csproj ./                                                                                                                                                                                                 0.0s 
 => CACHED [build-env 4/6] RUN dotnet restore                                                                                                                                                                                               0.0s 
 => CACHED [build-env 5/6] COPY . ./                                                                                                                                                                                                        0.0s 
 => CACHED [build-env 6/6] RUN dotnet publish -c Release -o out                                                                                                                                                                             0.0s 
 => CACHED [stage-1 3/4] COPY --from=build-env /app/out ./                                                                                                                                                                                  0.0s 
 => CACHED [stage-1 4/4] RUN useradd -ms /bin/bash moduleuser                                                                                                                                                                               0.0s 
 => exporting to image                                                                                                                                                                                                                      0.0s 
 => => exporting layers                                                                                                                                                                                                                     0.0s 
 => => writing image sha256:8d38fb01640fb566e761231c1a646df35bb83f24dfbb0fdea92bc4db62576e12                                                                                                                                                0.0s 
 => => naming to <...>

If I want to change the target platform to build an arm32 image, I change my settings.json file to:

    "azure-iot-edge.defaultPlatform": {
        "platform": "arm32v7",
        "alias": null

However I got this ugly error, trying to build this

=> CACHED [build-env 2/6] WORKDIR /app                                                                                                                                                                                                     0.0s 
 => CACHED [build-env 3/6] COPY *.csproj ./                                                                                                                                                                                                 0.0s 
 => ERROR [build-env 4/6] RUN dotnet restore                                                                                                                                                                                                0.5s
 > [build-env 4/6] RUN dotnet restore:
#10 0.450 A fatal error occurred, the folder [/usr/share/dotnet/host/fxr] does not contain any version-numbered child folders
executor failed running [/bin/sh -c dotnet restore]: exit code: 131

There seems to be an error here, outside of my docker knowledge.

Of course, a test path could involve the use of a remote ARM32 Docker Environment to build my Azure IoT Edge C# Module. I followed my previous posts steps to enable SSH password-less access to my Raspberry Pi and also manage docker as non-root users (see references).

Now I can define a specific DOCKER EXECUTOR to build my images. I changed my settings.json file to define this executor. Note that you must define a standard SSH connection, this may involve your device name or IP Address.

    "azure-iot-edge.defaultPlatform": {
        "platform": "arm32v7",
        "alias": null
    "azure-iot-edge.executor.env": {
         "DOCKER_HOST": "ssh://pi@<Raspberry PI Address>"

Important: once you changed your settings.json configuration, you need to reload your VSCode environment. You can close and open the IDE, or even better, invoke the [Reload Window] command.

visual studio code reload window

Now we can sucesfully build the Azure IoT module. the output log will be similar to this one:

Sending build context to Docker daemon  24.06kB
Step 1/12 : FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster-arm32v7 AS build-env
 ---> 3cdfdcca7cd6
Step 2/12 : WORKDIR /app
 ---> Using cache
 ---> 8c3252bfdefb
Step 3/12 : COPY *.csproj ./
 ---> Using cache
 ---> e6fe11cb659e
Step 4/12 : RUN dotnet restore
 ---> Using cache
 ---> 12453c83de65
Step 5/12 : COPY . ./
 ---> Using cache
 ---> 107c1dfccfa3
Step 6/12 : RUN dotnet publish -c Release -o out
 ---> Using cache
 ---> 603a93c80b0e
Step 7/12 : FROM mcr.microsoft.com/dotnet/core/runtime:3.1-buster-slim-arm32v7
 ---> 2bb8fc093aad
Step 8/12 : WORKDIR /app
 ---> Using cache
 ---> c8a93a2a7b90
Step 9/12 : COPY --from=build-env /app/out ./
 ---> Using cache
 ---> f72a492270ad
Step 10/12 : RUN useradd -ms /bin/bash moduleuser
 ---> Using cache
 ---> 082a4568867b
Step 11/12 : USER moduleuser
 ---> Using cache
 ---> 2c5e7b562289
Step 12/12 : ENTRYPOINT ["dotnet", "UDPFwder.dll"]
 ---> Using cache
 ---> f523123332f9
Successfully built f523123332f9
Successfully tagged <...>
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.

And that’s it! Using a Raspberry Pi device to build Net Azure IoT modules seems to be the fix to build ARM32 platforms.


Happy coding!


El Bruno

My posts on Raspberry Pi ⚡🐲⚡

Dev posts for Raspberry Pi
Tools and Apps for Raspberry Pi
Setup the device

¿Con ganas de ponerte al día?

En Lemoncode te ofrecemos formación online impartida por profesionales que se baten el cobre en consultoría:

#VisualStudioCode – Create and use Code Snippets in @code, and create custom snippets just for your workspace

Buy Me A Coffee

Hi !

Code Snippets are super useful, and create your custom Code Snippets is super easy in Visual Studio Code. The official Documentation (see references) explains how to create snippets, with the full details of the JSON file, sections, contents and more. However there are some extra tips on top of this information that are super useful.

Snippet Creator

This is an amazing Visual Studio Code Extension. Just search for [snippet creator] on the Extension and install the extension.

visual studio code snippet creator extension

Once the extension is installed, the way to use this is super simple.

  • Select some code
  • CTRL + SHIFT + P, and type [create snippet]
  • Follow the steps, define snippet prefix, and optionally description
  • That’s it!
visual studio code snippet creator add new snippet

I created a custom snippet with the prefix [cameraCalcFPS] and now the snippet is available for any python file !

visual studio code custom code snippet available

In order to check all the custom code snippets

  • CTRL + SHIFT + P
  • Type [configure user snippets]
  • Open the specific one, for this sample python.json

The code snippets file has all the custom created snippets

visual studio code open custom snippets for python

Workspace specific snippets

There is also another specific scenario which I found very interesting:

The need for specific snippets inside a workspace

In order to do this, just create a file [mysnippets.code-snippets] and paste your own snippets here. This snippets will be only available for this workspace!

snippets for a workspace

Happy coding!


El Bruno


#WindowsTerminal – Open Windows Terminal from the current edit file path in Visual Studio Code @code

Buy Me A Coffee

Hi !

I’m a big fan of Windows Terminal, and is my default external terminal in Visual Studio Code. However, today I learned a very cool tip:

Launch an external Windows Terminal from Visual Studio Code, and the terminal will open using the path of the current Workspace in VSCode.

Fabian explains the full scenario (see references), however the magic is to add the “startingDirectory = %__CD__%” in the profile definition in Windows Terminal Settings. In example, line 14:

      // Anaconda - Drone 02 Virtual Environment
      "guid": "{A87154C9-7846-479F-88CE-2C29BE4653CC}",
      "name": "Anaconda - Drone 02 VEnv",
      "commandline": "pwsh.exe -ExecutionPolicy ByPass -NoExit -Command & 'C:\\ProgramData\\Anaconda3\\shell\\condabin\\conda-hook.ps1' ; conda activate 'C:\\ProgramData\\Anaconda3' ; conda activate drone02; cls ",
      "hidden": false,
      "fontFace": "Cascadia Code",
      "fontSize": 12,                
      "backgroundImage": "D:/OneDrive/Pictures/WindowsTerminalBackgrounds/Ava_Wallpaper_Logo_Center_Thermal_Lat7270_5470.png",
      "backgroundImageOpacity" : 0.2,
      "colorScheme": "VibrantInk",
      "useAcrylic": true,
      "acrylicOpacity": 0.8,
      "startingDirectory": "%__CD__%" 

Awesome ! To open an external Terminal, press

Ctrl + Shift + C

and that’s it!

new terminal opened in the current workspace folder

Happy coding!


El Bruno


#VSCode – Let’s do some #FaceRecognition with 20 lines in #Python (7/N)

Buy Me A Coffee


I’m writing a series of posts about how to control a drone with Python and 20 lines of code, and once I reach to the point to read the camera feed, I’ve added a face detection sample. However this time I didn’t use the face_recognition python package I’ve used in this series, I performed the face detection using OpenCV and Haar Cascades. So, let’s explain a little what’s this.

Let me start quoting an amazing article “Face Detection using Haar Cascades” (see references)

Object Detection using Haar feature-based cascade classifiers is an effective object detection method proposed by Paul Viola and Michael Jones in their paper, “Rapid Object Detection using a Boosted Cascade of Simple Features” in 2001. It is a machine learning based approach where a cascade function is trained from a lot of positive and negative images. It is then used to detect objects in other images.

OpenCV comes with a trainer as well as detector. If you want to train your own classifier for any object like car, planes etc. you can use OpenCV to create one. Its full details are given here: Cascade Classifier Training.

And here we come to the cool part, OpenCV already contains many pre-trained classifiers for face, eyes, smile etc. Those XML files are stored in opencv/data/haarcascades/ folder (see references).

opencv github haar cascades files

Let’s take a look at a really [20 lines] sample code for face detection:

  • Line 6, we use OpenCV to load the haar cascade classifier to detect faces
  • Lines 9-20, main app
  • Lines 10-12, open a frame from the camera, transform the frame to a gray color scaled image and use the face cascade detector to find faces
  • Lines 14-15, iterate thought detected faces and draw a frame
  • Lines 17-20, display the webcam image with the detected faces, and stop the app when ESC key is pressed

And a live sample using a drone camera instead of an USB Camera

Bonus. Viola Jones Face Detection and tracking explained video

# Bruno Capuano
# detect faces using haar cascades from https://github.com/opencv/opencv/tree/master/data/haarcascades
import cv2
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cap = cv2.VideoCapture(0)
while True:
_, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (top, right, bottom, left) in faces:
cv2.imshow('Face Detection',frame)
k = cv2.waitKey(30) & 0xff
if k == 27:

This is a long video, however is an amazing entry point to understand how the Viola Jones algorithm works.

Happy coding!


El Bruno


#RaspberryPi – Visual Studio Code blank screen is fixed on version 1.42. Thanks @headmelted! @code

Buy Me A Coffee


When I wrote about how to install Visual Studio Code on a Raspberry Pi, there was an error on the app running on the device: the tool opened and display a black window.

We needed to manually go back to version 1.29 to avoid this problem. And we also forgot to apply any updates, each new version still have the black window error.

I was following the issue on GitHub, and I was happy when a few days ago, it was solved by headmelted (link https://github.com/headmelted/codebuilds/issues/67#issuecomment-563335451).

I’ve updated the app to the latest version (1.42.0), and it was working fine.

raspberry pi 4 visual studio code version 1.42 running fine

If we check the apt list, we can find a specific detail of the running version with the command

sudo apt list --installed | grep -i code-oss
raspberry pi 4 apt list for code -oss return 1.42

So, please go and thank headmelted by the amazing work he is doing!

Happy coding!


El Bruno

My posts on Raspberry Pi ⚡🐲⚡

Dev posts for Raspberry Pi
Tools and Apps for Raspberry Pi
Setup the device

#VSCode – Installing Visual Studio Code @code in a #RaspberryPi, run as root, fix black screen (Updated)

Buy Me A Coffee


TL;DR: These 2 commands are the only ones you need to install

wget https://packagecloud.io/headmelted/codebuilds/gpgkey -O - | sudo apt-key add –
curl -L https://code.headmelted.com/installers/apt.sh | sudo bash

At the bottom of the post you will also find the command to run Visual Studio Code as Root in RPI

Some history on installing VSCode in a Raspberry Pi

Now that I have my amazing Raspberry Pi 4 with 4GB RAM, it’s time to see how serious the device is. So, I decided to install and use some developers’ tools in the RPi. My dev list will be something like this

  • Python
  • Some ML and AI Python packages
  • GIT
  • Arduino
  • Visual Studio Code

It’s been a while since I installed VSCode in the device. The last time I did this, I needed to download the code from GitHub and compile the tool in the Raspberry Pi. As far as I remember this was a +25 min process.

Lucky for us the process can now be much simpler, thanks to Headmelted (see references). Now, we only need a single command to install VSCode:

. <( wget -O - https://code.headmelted.com/installers/apt.sh )

Install process started! Or Maybe not because I found this amazing GPG error

python error installing visual studio code in raspberry pi
pi@rpidev3:~ $ curl -L https://code.headmelted.com/installers/apt.sh | sudo bash
   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                  Dload  Upload   Total   Spent    Left  Speed
 100  2349    0  2349    0     0  19739      0 --:--:-- --:--:-- --:--:-- 19906
 Detecting architecture…
 Ensuring curl is installed
 Reading package lists… Done
 Building dependency tree       
 Reading state information… Done
 curl is already the newest version (7.64.0-4).
 The following packages were automatically installed and are no longer required:
   python3-pyperclip python3-thonny rpi.gpio-common
 Use 'apt autoremove' to remove them.
 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
 Architecture detected as armv7l…
 Retrieving GPG key headmelted…
   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                  Dload  Upload   Total   Spent    Left  Speed
   0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
 gpg: no valid OpenPGP data found.
 Removing any previous entry to headmelted repository
 Installing [headmelted] repository…
 Updating APT cache…
 Hit:1 http://raspbian.raspberrypi.org/raspbian buster InRelease
 Hit:2 http://archive.raspberrypi.org/debian buster InRelease
 Get:3 https://packagecloud.io/headmelted/codebuilds/debian stretch InRelease [23.4 kB]
 Err:3 https://packagecloud.io/headmelted/codebuilds/debian stretch InRelease
   The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 0CC3FD642696BFC8
 Reading package lists…
 W: GPG error: https://packagecloud.io/headmelted/codebuilds/debian stretch InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 0CC3FD642696BFC8
 E: The repository 'https://packagecloud.io/headmelted/codebuilds/debian stretch InRelease' is not signed.
 Repository install complete.
 Installing Visual Studio Code from [stretch]…
 Reading package lists… Done
 E: The value 'stretch' is invalid for APT::Default-Release as such a release is not available in the sources
 Visual Studio Code install failed.

There a public GPG key used to verify the package and the SH script somehow does not download it (I think the ARM RPI version is still not defined). So, before the previous command, I need to run this command

wget https://packagecloud.io/headmelted/codebuilds/gpgkey -O - | sudo apt-key add –

Then run this command

curl -L https://code.headmelted.com/installers/apt.sh | sudo bash

Now we have Visual Studio Code installed!

raspberry pi visual studio code installed

Old Issue, not needed since 2020 January

But, yes another but, you may note that the tool open and display a black window. Again, I need to go deeper on the details, but the latest version does not work well. There is some context information on GitHub (see references), and the proposed solution is to rollback to a previous version

sudo apt-get install code-oss=1.29.0-1539702286

And we also need to disable the automatic updates on this tool

sudo apt-mark hold code-oss

The following command will remove the hold for Visual Studio Code

sudo apt-mark unhold code-oss

And now, yes, we got a fully functional Visual Studio Code in our Raspberry Pi!

How to run VSCode as root

Another update, is a command to run VSCode as root

# open VSCode in default source code folder with root
sudo code-oss --user-data-dir=/home/pi/src/vsCodeUsrData

Of course this is not the best way to use Visual Studio Code, however something it helps 😀

Note: Due some Deep Neural Network and docker process, my device is starting to heat a lot, so I’ll try a next generation cooler like this one: Blink Blink ICE Tower CPU Cooling Fan for Raspberry Pi (Support Pi 4)

Happy Coding!

Greetings @ Toronto

El Bruno


My posts on El Bruno

My posts on Raspberry Pi ⚡🐲⚡

Dev posts for Raspberry Pi
Tools and Apps for Raspberry Pi
Setup the device

#VSCode – Let’s do some #Git dev in #RaspberryPi (GitHub and Azure DevOps!)

Buy Me A Coffee


In my previous posts I wrote about how to prepare a developer station with a Raspverry Pi 4. I wrote on how to install Visual Studio Code, how to install .Net Core and how to build and run C# projects. Of course, the next step is to work with Git.

The command to install git is

apt-get install git

However, I already have Git installed. I haven’t checked, but it seems to me that the latest Raspbian distro includes by default git. I was hoping that VSCode will recognize and use this, but in order to work with Git in VSCode I need some extra work in the IDE settings.

raspberry pi git installed but not integrated in visual studio code

I was able to clone some repositories from GitHub and Azure DevOps, directly from bach

raspberry pi 4 git clone azure devops repository

So, let’s fix Visual Studio Code and Git integration. This one is very easy, I just need to go to Settings, search for Git and define the Git path for VSCode.

raspberry pi 4 visual studio code preferences git

In order to find the git path, we need to use the [which] command

pi@rpidev3:~ $ which git


My got location is [/usr/bin/git].

I’m not a command line dude! I like User Interfaces, so now it’s time to open one of the cloned repositories in Visual Studio Code. I can see that VSCode recognices Git and I can start to commit my files.

raspberry pi 4 visual studio code using git

This is also a perfect moment to define Git user name and user email.

git config --global user.email "email@email.com" 
git config --global user.name "your name"

I like to do this in the Terminal in VSCode, just to check all is working fine.

Happy coding!


El Bruno

My posts on Raspberry Pi ⚡🐲⚡

Dev posts for Raspberry Pi
Tools and Apps for Raspberry Pi
Setup the device

#VSCode – Build and Run C# #DotNetCore projects in #RaspberryPi


Time to move on with some lessons learned using Visual Studio Code in the Raspberry Pi 4.

One of the first issues you may find working with VSCode in the device is related to file write permissions when you are saving a file.

I raspberry pi 4 visual studio code failed to save file

So, it was a good opportunity for me to learn about files and folder permissions in Linux. I found a great starting article “How to Manage File and Folder Permissions in Linux” (see references), and it allowed me to fix this issue.

My next error was triggered when I try to build my project. Again, it was a permission related error.

error MSB3021: Unable to copy file "obj/Debug/netcoreapp2.2/dotnethelloworld.dll"
to "bin/Debug/netcoreapp2.2/dotnethelloworld.dll". Access to the path
is denied. [/home/pi/dotnethelloworld/dotnethelloworld.csproj]

However, this time the fix was not related to file and folder permissions.

One of the solutions I found, was to run VSCode with admin privileges. This is probably one of the worst ideas ever, and you can find tons of articles explaining why this is bad (see references).

Anyways, I decided to give it a try. Of course, it worked. Let me share how.

I run VSCode with the following command, which runs the app in root mode.

code-oss --user-data-dir=/home/pi/dotnethelloworld
raspberry pi 4 visual studio code run as root

The VSCode team is aware of this, so you will find a warning about this scenario

raspberry pi 4 visual studio code run as root warning

Even so, you can still use VSCode to edit and build C# .Net Core Projects.

raspberry pi 4 visual studio code build code

And you can run them also

raspberry pi 4 visual studio code build and run edited code

So far, so good. Or maybe not, broken a lot of good practices. I’ll see this as an amazing chance to learn and test new stuff!

Happy coding.

Greetings @ Burlington

El Bruno


My posts on Raspberry Pi ⚡🐲⚡

Dev posts for Raspberry Pi
Tools and Apps for Raspberry Pi
Setup the device