Skip to main content

Kalliope update

Hello,

Quick blog post as I reinstall my Kalliope setup that I quit for a while :)

First, the good news is that i'm impressed by the amount of work the team as done! If you haven't tried it yet for a while, I suggest you retry it now :]

From what I've seen so far:

A lot of performance improvement has been done and now it is faster than ever on a raspberry pi! And also a lot of bug fixes too where done :)

New feature concerns hardware improvement:

  • LED
  • Mute button:
  • Sound sensibility (for the mic)

And lots of new features:

  • Player modularity: you can select your own player instead of default one
  • No voice via API: now, api call don't have to active audio response, so you can use kalliopé in a client / server configuration (very excited by that one !) :]
  • Kalliope memory: Awesome feature to store data in memory for later reuse ! (only temp memory though!)
  • New neurons has been developed too:
  • Neurotimer: So you can plan to launch other neuron at a specific time :) or even can use this to create a remember app via kalliopé (So my previous script is now useless)
  • MQTT neuron integration (as well as a signal to start a neuron via MQTT signal)
  • Mute neuron to pause kalliope from waking up

And other stuff too, check out the github page!

Now, I have started checking my neurons to see if they are still working. Google agenda, Repeat and System status are working fine.

Web scrapper and all orders ones seem to be broken though… I'll check that soon.

I haven't checked the other yet but I'll do it soon too :)

My TODOs:

  • Repair neurons
  • Test the Mobile app via the API
  • Repair my web app
  • Redo the Kalliope CLI
  • duckduckgo AI API neuron

++

What have I been up to lately

Still alive ?

Yes! I know I've posted a lot in January / February and disappeared a bit after that ^^. I have been busy at work and at home, and to be honest I started working on another topic of my "todo geek list" : Reinstalling my servers where I host my application and retake ownership of my data.

I also wanted to switch for manual installing all software on my servers and leveraging docker to put the app within container (and also improve a bit my knowledge in this area^^)

Here is what I have setup so far (all on docker containers):

As you can see, i have been busy (with this, work, my life and of course starcraft2 ^^"), but unfortunately, I'm not done yet^^

My todolist still contains:

  • Migrate all my repos from github to Gogs (at least mirroring)
  • Add mattermost bots (hubot and RSS)
  • Monitoring alerts via email (?)
  • Redo mail server
  • Backup automated policy

Ok... That's cool, but why ?

Well, since a long time now, I'm trying to advocate for data privacy, self hosting a trying to stop feeding (too much) the GAFAM. I'm hosting my own server mail since 10 years as well as my websites (like this blog), but i wanted to go further and take ownership again of my data.

For those who speaks french and didn't see it (old from 2007… but still so true), i recommend this great video of Benjamin Bayart: Internet or minitel 2.0 (For non French people, look up online what Minitel was :)).

From what I read on mastodorn, it seems B. Bayart might do a new version of that talk :). I don't really want to explain why you should care about your data, there are a lot of good articles online.

Sounds cool, i want to do it!

I'm planing to transform this experience into a series of blog posts:

  • Continuous integration setup: Gogs , DroneCI and automatic builds when a push happens. Bonus: push notification on a private channel of my mattermost instance.
  • Mastodon and feed2toot bot (will be an update of my previous post about feed2toot as I don't plan to rewrite the good installation doc)
  • Cool / useful apps selfhosted apps on RaspberryPi: Wallabag, Shaarli and Lutim
  • Mattermost and Hubot
  • Monitoring, graph and alerts

I'll update this post to add the link to the post series.

Talk to you soon!

Running feed2toot in a docker container

Introduction

Today, a very quick blog post on a how to install feed2toot in a docker container. Feed2toot is a python application that will send toot on Mastodon for each item of an RSS feed.

If you want to install Mastodon, I suggest you read here: - Offical documentation - Intall guide for Digital ocean - French intall guide on Debian

if you want to install feed2toot in a container to be able to create toot from an RSS feed, then keep reading :).

Create the docker image

Get the files

You can start with my repo as a base:

git clone https://git.bacardi55.org/bacardi55/docker-feed2toot.git

Build the container image

cd docker-feed2toot
docker build -t b55/feed2toot .

You can change the tag name :)

Configure feed2toot

Edit the conf/feed2toot.ini, conf/rsslinks.txt and conf/hashtags.txt files as describe in the official documentation

The current release needs a hashtags file, even empty! It will become optional in the next release

Run

Get your credential first

Then, register your application with your mastodon account:

docker run --rm -v "$(pwd)"/conf:/etc/feed2toot -it b55/feed2toot register_feed2toot_app

It will ask your password (but won't save it) to generate token files.

Test the first run

docker run --rm -v "$(pwd)"/conf:/etc/feed2toot b55/feed2toot

Go to your user mastodon page, you should see the toot generated :)

Automate

To avoid launching the app manually, let's put a simple task in our crontab:

Open the crontab file: crontab -e and insert this line:

@hourly docker run --rm -v /path/to/conf:/etc/feed2toot b55/feed2toot

And you should be good to go!

Kalliopé 4.3 and new kalliopé website and videos!

Today, a quick note to indicate some improvement in Kalliopé with the v4.3 version and it's documentation!

Quick reminder Kalliopé is personal vocal assistant, so you act like Tony Start… Well almost… :) Well… At least you'll be able to: - Retrieve data on the web (wikipedia, weather, agenda, email, gmaps, uber, twitter, facebook, RSS feeds, or simply by reading part of webpage) - Manage a todolist (compatible with todotxt format) - Listen to music (via an MPD or Mopidy server) - Manage your domotic simply via http(s), or via device library (Philips HUE) or via a domotic application API (domoticz, LoxSControl) - Run shell scripts or cli commands - Get the time of any places in the world - … And other cool stuff!

And of course, you can add your own neuron and reference it on the neuron marketplace page to improve Kalliopé for everyone!

If you haven't seen this video yet, this is a broad example of what Kalliopé can do (video in English):

{% youtube "https://www.youtube.com/watch?v=PcLzo4H18S4" %}

Great job Sispheor for the demo and the website!

On the neuron marketplace, look for the play icon ![play icon]({{ site.url }}/assets/kalliope-doc-play.png) for each neuron. If it has one, it means there is a dedicated page and a video to demonstrate the neuron, so feel free to browse :). Most of the videos are in French but some have English subtitles!

But for the lazy, if you just want to browse the video, I created this playlist on youtube with all current videos :) More video are to come :)

For the occasion, I've also created a dedicated Kalliopé page on this blog, where you can find the videos links, my neurons, scripts and all my kalliopé blog posts.

Stay tune for more cool Kalliopé stuff!

Kalliopé, what time is it in …

Introduction

When you work with multiple country and different timezone, you're always wondering what time it is there… And I was fed up to keep opening a tab in a browser to find out again and again.

So I decided to create a kalliopé neuron to be able to ask kalliopé what time it is in any city / country :) and I create the [wwtime neuron]https://github.com/bacardi55/kalliope-wwtime() to do so!

How

Getting timezone for address

This neuron will retrieve a local timezone and a requested city timezone. It compares timezone difference (including summer time) between the two location to give you the time there based on your timezone.

Eg:

  • I am in Paris (GMT +1)
  • I want to know Boston time (GMT -5 - and as of now - summer time (so 1 additional hour))

When it's 10pm in Paris, Kalliope will tell me it is 5pm in Boston (because as of now, boston is in summer time and paris not yet, so -5 and not -6)

It uses GoogleMaps API to get geolocation data based on a city name or address. So you need to activate to Google API:

To make it works, you will need to get an API key on your developer console. Or follow documentation here and here

Installation

.. code:: bash

kalliope install --git-url https://github.com/bacardi55/kalliope-wwtimes.git

Options

parameter required default choices comment
gmaps_api_key yes string The api key to use googlemaps API. See above.
local yes string Your city/address to compare time difference with
city yes string What city/address where you want to know time

Return Values

Name Description Type sample
status Response status String OK or KO
city A dict¹ (see below) dict [arg: 'new york city', 'timezoneid': 'America/New_York', 'timezonename': 'Eastern Daylight Time', time:
local A dict¹ (see below) dict [arg: 'Paris France', 'timezoneid': 'Europe/Paris', 'timezonename': 'Central European Standard Time', time:

¹: these dict contains:

  • arg: The given name in arguments (equals 'local' argument for local return variable or 'city' arguments for city return variable)
  • timezoneid: The ID of the timezone, eg: Europe/Paris
  • timezonename: The name of the timezone eg: Central European Standard Time
  • time, a dict containing 'hour' and 'minutes'

Synapses example

brains

Get a city by argument in order

.. code:: yaml

  - name: "Wwtime-city"
    signals:
      - order: "what time is it in {{city}}"
    neurons:
      - wwtime:
          gmaps_api_key: "{{gmaps_api_key}}"
          local: "Paris France"
          args:
            - city
          file_template: "templates/fr_wwtime.j2"

Get a city by argument set in brain:

.. code:: yaml

  - name: "Wwtime-city-boton"
    signals:
      - order: "heure boston"
    neurons:
      - wwtime:
          gmaps_api_key: "{{gmaps_api_key}}"
          city: "boston MA"
          local: "Paris France"
          file_template: "templates/fr_wwtime.j2"
template

.. code:: jinja

{% raw %}
{% if status == "OK" %}
    Sir, in {{city.arg}}, it is {{city.time.hour}} hour and {{city.time.minute}} minutes, whereas here, it's {{local.time.hour}} hour and {{local.time.minute}} minutes
    Le timezone est {{city.timezonename}}
{% else %}
    Sorry sir, but I don't know
{% endif %}
{% endraw %}

see more example in the sample directory

An Uber neuron for Kalliope

Introduction

Today I realized that I didn't write about a neuron I did for Kalliopé to interact with the Uber API that I've done a couple of weeks following a "silly bet" with my brother after I've done the Google maps neuron

The basic idea was to see what could be done without validating any drive order. Indeed, as of now, I find it too dangerous that someone could by a voice command order a driver (or anything payment related).

Plus, to do this automatic order, you need more permission (end user permission as opposed to server to server permissions) and that complexified too much the neuron (coded in a 7h flight ^^).

The neuron

What can it do ?

Basically, this Uber neuron let you ask for how long to get a Uber based on an address and a Uber type (X, Black, Pool, …)

It also let you put an optional end address. In that case, you will also have a estimation of the cost and the duration of a drive from a start address to this destination.

Installation

.. code:: bash

kalliope install --git-url https://github.com/bacardi55/kalliope-uber.git

Usage:

Brains

Get the estimated time to get a driving_mode driver based on geolocation data

.. code:: yaml

{% raw %}
  - name: "Uber-time-estimate"
    signals:
      - order: "how long for a driver to pick me up"
    neurons:
      - say:
          message: "Calculating"
      - uber:
          uber_api_key: "***********************"
          start_longitude: "***"
          start_latitude: "****"
          driving_mode: "uberX"
          say_template: "A {{driving_mode}} driver can be there in {{ time_to_get_driver }} minutes"
{% endraw %}

Get the estimated time to get a driving_mode based on a text address

.. code:: yaml

{% raw %}
  - name: "Uber-time-estimate-by-address"
    signals:
      - order: "how long for a driver to pick me up"
    neurons:
      - say:
          message: "Calculating"
      - uber:
          uber_api_key: "***********************"
          gmaps_api_key: "**********************"
          start_address: "*********"
          driving_mode: "uberX"
          say_template: "A {{driving_mode}} driver can be there in {{ time_to_get_driver }} minutes"
{% endraw %}

Get the estimated time to get a driving_mode, the price and the ride duration

.. code:: yaml

{% raw %}
  - name: "Uber-time-and-price"
    signals:
      - order: "how much for a rider to work"
    neurons:
      - say:
          message: "Calculating"
      - uber:
          uber_api_key: "***********************"
          driving_mode: "uberX"
          start_longitude: "***"
          start_latitude: "****"
          end_longitude: "*****"
          end_latitude: "******"
          say_template: "A {{driving_mode}} driver can be there in {{ time_to_get_driver }} minutes. Traject will take about {{ duration }} and would cost {{ estimate }}"
{% endraw %}

Get the estimated time to get a driving_mode, the price and the ride duration to go to an address givin in argument

.. code:: yaml

{% raw %}
  - name: "Uber-time-and-price-by-addresses"
    signals:
      - order: "how much for a rider to {{end_address}}"
    neurons:
      - say:
          message: "Calculating"
      - uber:
          uber_api_key: "***********************"
          gmaps_api_key: "**********************"
          start_address: "*********"
          driving_mode: "uberX"
          say_template: "A {{driving_mode}} driver can be there in {{ time_to_get_driver }} minutes. Traject will take about {{ duration }} and would cost {{ estimate }}"
          args:
              - end_address
{% endraw %}

Get the estimated time to get a driving_mode, the price and the ride duration based on addresses given in arguments

.. code:: yaml

{% raw %}
  - name: "Uber-time-and-price-by-start-address"
    signals:
      - order: "how long for a driver to pick me up {{start_address}} to go to {{end_address}}"
    neurons:
      - say:
          message: "Calculating"
      - uber:
          uber_api_key: "***********************"
          gmaps_api_key: "**********************"
          driving_mode: "uberX"
          say_template: "A {{driving_mode}} driver can be there in {{ time_to_get_driver }} minutes. Traject will take about {{ duration }} and would cost {{ estimate }}"
          args:
              - start_address
              - end_address
{% endraw %}

see more example in the sample directory

enjoy!

Switching back to static html

Quick note to say I've switched back to static html site, managed (this time) by jekyll :).

The reason behind that is simple: it's way easier to maintain and secure a stack for html files than php or other :).

And even though I enabled the markdown text format, I still feel more comfortable writing in vim and commiting blog post like code via git (: