Ben's Blog

Category: I.T.

207 Articles
I.T. ben April 02, 2020

PHP Zoom API JWT Bit Banging

It’s always hard to nail the exact sequence when authorizing through a new API. Here’s what I came up with for PHP authorization with Zoom’s JWTs. This is essentially a quick start which gets you enough functions to do a first API call: to list zoom users. Line 40->68 is where the JWt meat happens.

[php]
<?php

// config parameters you need to define
define( ‘ZOOM_TOKEN_FILE’, "/var/.zoom_token" ) ; // some location on the filesystem used to cache your token while it’s current (make sure permissions are restrictive)
define( ‘ZOOM_API_KEY’, "" ) ;
define( ‘ZOOM_API_SECRET’, "" ) ;

// main
print_r( zoom_list_users() ) ;
exit( 0 ) ;

// functions
function zoom_list_users() {
$users = array() ;

$page_number = 1 ;
$keep_going = true ;
while( $keep_going && $page_number<10000 ) {
$result = zoom_make_api_call( "GET", "https://api.zoom.us/v2/users", array(‘page_size’=>300, ‘page_number’=>$page_number, ‘status’=>"active") ) ;
$result = json_decode( $result, true ) ;
if( array_key_exists(‘users’, $result) &&
count($result[‘users’])>0 ) {
foreach( $result[‘users’] as $user ) {
$users[] = $user ;
}
$page_number++ ;
if( $page_number>$result[‘page_count’] ) {
$keep_going = false ;
}
} else {
$keep_going = false ;
}
}

return $users ;
}

// PHP’s default base64 encode isn’t URL safe which messes up the JWT, we need these functions instead
function base64_url_encode( $data ) {
return rtrim( strtr(base64_encode($data), ‘+/’, ‘-_’), ‘=’ ) ;
}
function base64_url_decode( $data ) {
return base64_decode( str_pad(strtr($data, ‘-_’, ‘+/’), strlen($data) % 4, ‘=’, STR_PAD_RIGHT) ) ;
}

function get_token( $refresh=false ) {
if( $refresh===false &&
file_exists(ZOOM_TOKEN_FILE) ) {
return file_get_contents( ZOOM_TOKEN_FILE ) ;
}

$jwt_request_date = @date( "U" ) ; // no warning, proper system timezone assumed
$jwt_expiration_date = $jwt_request_date + 60*60 ; # +1 hour
$jwt_header = ‘{"alg":"HS256","typ":"JWT"}’ ;
$jwt_claim_set = ‘{"iss":"’ . ZOOM_API_KEY . ‘","exp":’ . $jwt_expiration_date . ‘}’ ;
$jwt_signature = sign_data( base64_url_encode($jwt_header) . ‘.’ . base64_url_encode($jwt_claim_set), ZOOM_API_SECRET ) ;
$jwt = base64_url_encode( $jwt_header ) . "." . base64_url_encode( $jwt_claim_set ) . "." . base64_url_encode( $jwt_signature ) ;

file_put_contents( ZOOM_TOKEN_FILE, $jwt ) ;
return $jwt ;
}

function sign_data( $data, $key ) {
return hash_hmac( "SHA256" , $data, $key, true) ;
}

function zoom_make_api_call( $request, $url, $get_variables=null, $post_variables=null, $force_refresh_token=false ) {
$ch = curl_init() ;
$token = get_token( $force_refresh_token ) ;

$getfields = "" ;
if( $get_variables!==null && is_array($get_variables) ) {
foreach( $get_variables as $get_variable_key=>$get_variable_value ) {
$getfields .= "&" . urlencode( $get_variable_key ) . "=" . urlencode( $get_variable_value ) ;
}
if( strlen($getfields)>0 ) {
$getfields = "?" . substr( $getfields, 1 ) ;
}
}

curl_setopt( $ch, CURLOPT_URL, "{$url}{$getfields}" ) ;
curl_setopt( $ch, CURLOPT_PORT , 443 ) ;
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, $request ) ;
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false ) ;
if( $post_variables!==null && is_array($post_variables) ) {
$postfields = "" ;
foreach( $post_variables as $post_variable_key=>$post_variable_value ) {
$postfields .= "&" . urlencode( $post_variable_key ) . "=" . urlencode( $post_variable_value ) ;
}
$postfields = substr( $postfields, 1 ) ;
curl_setopt( $ch, CURLOPT_POSTFIELDS, $postfields ) ;
} else if( $post_variables!==null && is_string($post_variables) ) {
curl_setopt( $ch, CURLOPT_POSTFIELDS, $post_variables ) ;
}
curl_setopt( $ch, CURLOPT_HTTPHEADER, array( "authorization: Bearer {$token}",
"content-type: application/json") ) ;

curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ) ;
curl_setopt( $ch, CURLOPT_HEADER, true ) ;

$response = curl_exec( $ch ) ;
curl_close( $ch ) ;

$response = parse_http_response( $response ) ;

if( $response[‘code’]=="200" ||
$response[‘code’]=="204" ||
$response[‘code’]=="404" ) {
return $response[‘body’] ;
} else if( $response[‘code’]=="401" ) { // expired token
if( $force_refresh_token===false ) {
// safe to recurse
return zoom_make_api_call( $request, $url, $get_variables, $post_variables, true ) ;
} else {
echo "ERROR: had an expired token and I tried to refresh it, yet somehow it’s still expired\n" ;
print_r( $response ) ;
exit( 1 ) ;
}
} else {
echo "ERROR: I have no idea what to do with this response from Zoom\n" ;
print_r( $response ) ;
exit( 1 ) ;
}
}

function parse_http_response( $raw_data ) {
$parsed_response = array( ‘code’=>-1, ‘headers’=>array(), ‘body’=>"" ) ;

$raw_data = explode( "\r\n", $raw_data ) ;

$parsed_response[‘code’] = explode( " ", $raw_data[0] ) ;
$parsed_response[‘code’] = $parsed_response[‘code’][1] ;
$i = 1 ;
if( $parsed_response[‘code’]=="100" ) {
$parsed_response[‘code’] = explode( " ", $raw_data[2] ) ;
$parsed_response[‘code’] = $parsed_response[‘code’][1] ;
$i = 3 ;
}

for( ; $i<count($raw_data) ; $i++ ) {
$raw_datum = $raw_data[$i] ;

$raw_datum = trim( $raw_datum ) ;
if( $raw_datum!="" ) {
if( substr_count($raw_datum, ‘:’)>=1 ) {
$raw_datum = explode( ‘:’, $raw_datum, 2 ) ;
$parsed_response[‘headers’][strtolower($raw_datum[0])] = trim( $raw_datum[1] ) ;
} else {
echo "ERROR: we’re in the headers section of parsing an HTTP section and no colon was found for line: {$raw_datum}\n" ;
exit( 1 ) ;
}
} else {
// we’ve moved to the body section
if( ($i+1)<count($raw_data) ) {
for( $j=($i+1) ; $j<count($raw_data) ; $j++ ) {
$parsed_response[‘body’] .= $raw_data[$j] . "\n" ;
}
}

// we don’t need to continue the $i loop
break ;
}
}

return $parsed_response ;
}

?>
[/php]

homestead automation, I.T. ben January 12, 2020

GPIO 2 Inverter

I figured out a way to turn our inverter on and off with a Pi so I can leave it off when Winter forces us to be frugal. It takes a little more than an amp hour just sitting there doing nothing, so I do like to turn it off. This capability will serve to automate the fridge in the future, before I do that though, I need to figure out a way to bring cold air from the outside into it. The idea is to have a logic which looks at outside temperature, solar status, and fridge temperature to decide if we just turn it on or if we can simply (and for less electricity) fan in cold air from the outside.

Running a fridge on the coldest months, when solar power is scarce, is doubly absurd.

aesthetics, I.T., plotters ben January 12, 2020

Plotter Trials

I’m getting closer to a very usable plotter, for now the prototype is serving all my plotting needs. Another prototype is in the works, this way I’ll be able to work on a plotter and keep another one for drawing. I keep finding ideas for really cool videos which I’m certain will make splashes online. I want to have my next steps figured out before I try to do just that. I know that at least the plotter build will be documented as a DYI project.

I found my birthday presents for the next 10 years

First trial with paint, I coded for “ink refill” capabilities for all instruments which require it. Obviously I’ve learned a few lessons here ๐Ÿ™‚

I.T., plotters ben January 01, 2020

Protected: Learning about Cartesian coordinate systems to control the plotter

This content is password-protected. To view it, please enter the password below.

electronics, I.T. ben December 14, 2019

Raspberry Pi Servo Jitter

Here’s the final solution I came up with to finally get a servo motor to behave on a Pi. It may not seem like much but it took a lot of doing to gather all the right bits. This was tested with an SG90, SG92R, and an MG90S on a Pi Zero.

Scroll straight to the end for the solution.

The most common way for controlling a servo motor on a Pi with is through RPi.GPIO as such:

#!/usr/bin/python3
import RPi.GPIO as GPIO
import time

servo = 23

GPIO.setmode( GPIO.BCM )
GPIO.setup( servo, GPIO.OUT )

# info on frequency and PWM formula at https://rpi.science.uoit.ca/lab/servo/
pwm = GPIO.PWM( servo, 50 )
pwm.start( 2.5 )

print( "0 deg" )
pwm.ChangeDutyCycle( 2.5 )  # turn towards 0 degree
time.sleep( 3 )

print( "90 deg" )
pwm.ChangeDutyCycle( 7.5 )  # turn towards 90 degree
time.sleep( 3 )

print( "180 deg" )
pwm.ChangeDutyCycle( 12.5 ) # turn towards 180 degree
time.sleep( 3 )

pwm.stop()
GPIO.cleanup()

Stuff you might need for this to run:

sudo apt-get update && sudo apt-get install python3-rpi.gpio

It results in super jitter which is unacceptable for the holy mission of pen plotting.

As far as I understand, the jitter comes from the wave form RPi.GPIO produces for Pulse Width Modulation, which is made in software and so it’s not super stable (no dedicated resources to build it). From what I gather, pigpio is programmed to tap into the one hardware PWM that Pis have.

The solution thus is as such:

#!/usr/bin/python3
import RPi.GPIO as GPIO
import pigpio
import time

servo = 23

# more info at http://abyz.me.uk/rpi/pigpio/python.html#set_servo_pulsewidth

pwm = pigpio.pi()
pwm.set_mode(servo, pigpio.OUTPUT)

pwm.set_PWM_frequency( servo, 50 )

print( "0 deg" )
pwm.set_servo_pulsewidth( servo, 500 ) ;
time.sleep( 3 )

print( "90 deg" )
pwm.set_servo_pulsewidth( servo, 1500 ) ;
time.sleep( 3 )

print( "180 deg" )
pwm.set_servo_pulsewidth( servo, 2500 ) ;
time.sleep( 3 )

# turning off servo
pwm.set_PWM_dutycycle( servo, 0 )
pwm.set_PWM_frequency( servo, 0 )

Stuff you might need for this to run:

sudo apt-get update && sudo apt-get install python3-pigpio
sudo pigpiod

And the resulting super smooth motion and holds:

aesthetics, I.T., web development ben December 08, 2019

Fibonacci Assist

It’s been a while since I pushed a feature to Mandalagaba worthy of a post.

I just pushed a tool I call “Fibonacci Assist”. It’s meant to help you draw Fibonacci spirals by overlaying the proper framing based on the beginning of your penstroke.

I was reminded of the existence of this sequence and its ties to nature reading the most excellent children book: Swirl by Swirl. The book is simply magnificent and so I thought I’d do my part to help bring into the world more Fibonacci spirals.

I have yet to play with it using a stylus.

aesthetics, all out geekery, I.T. ben December 07, 2019

Fluid Dynamics Simulation

all out geekery, I.T. ben December 07, 2019

Nosy Monster Nosying & Monstering around

Still going strong

3D modeling / printing, aesthetics, I.T., plotters ben December 02, 2019

Plotting Plotters

Well so, I fell into a very deep rabbit hole. The world of pen plotters… A year in, I finally have some good results. After several prototypes of Gondola plotters (V-plotters) and regular tabletop plotters. I’ve homed in on a set of designs, hardware, electronics, and algorithms to think I can make a small difference in that world. I still need to iterate a little but I’m hoping to release each plotter as a DYI projects in 2020. Maybe I’ll even sell my making them for others. Of course there will be integrations with Mandalagaba because that just makes sense.

Now there are several such plotters one can buy or build for a wide range of prices. And they all have a very shitty software stack. This is where I believe I can make the biggest difference.

As with building houses, it’s enormously relieving to finally see into the real world a model you’ve been immersed in, CADing it for a year.

I’ll skip talking about the long series of challenges I ran into building this. It’s really, really nice to see a long plot finished to perfection knowing that finally, nothing is wrong. I’ve learned a lot along the way.

There’s a bazillion pen plotters on Thingiverse, I’ve used some of them as stepping stones until I was ready to finally make my own top to bottom. As I said, software is where I think I can make the biggest difference. I’m a Raspberry Pi aficionado, and this opens the door to a sophisticated software stack (web servers, HTML canvasses, format conversion, penstroke optimization, live link with Mandalagaba). I found not a single plotter using a Pi, in fact I found very few projects of anything using stepper motors with a Pi. I had to do some serious trail blazing to step a motor reliably.

Here is for example a pen stroke optimization algorithm I developed to speed up plotting.

 

The base, drawing penstrokes as they come. “Empty” travel going from one penstroke to the next without the pen drawing: ~36437 (relative pixels).

The next penstrokes is the closest. Empty travel ~15820, 0.43 compression ratio.

The next penstrokes is the closest, but consider its beginning as well as its end, draw the penstroke reversed if it was the end which was closest. Empty travel ~12467, 0.34 compression ratio.

 

Now for the eye candy ๐Ÿ™‚

I could watch this for hours, and I did.

Of course the efficacy of this algorithm depends heavily on the model to be drawn. I found that anything coming from Mandalagaba tends to benefit enormously, especially tessellations. And it makes sense, for every penstroke drawn, the repetitions occur throughout the canvas and they show up in that order even if you drew in a very localized area. The example above comes from the most excellent turtletoy.net.

More to come very soon on the great world of plotters…

I.T., maniacal paranoia ben November 17, 2019

Paranoia Through Inertia

I.T., maniacal paranoia ben November 10, 2019

Relinquish your own thoughts

Slowly but surely, we are foregoing self agency to algorithms.

2019 Gmail settings:

3D modeling / printing, building, self sustainability ben September 13, 2019

How I build

Winter on a computer, Summer on a ladder.


I.T., web development ben June 14, 2019

Insulted & Honored

Someone ripped an early version of Mandalagaba, removed any mention of it, translated it, and is hosting it as their own.

Feels like I somehow made it as a developer to have my work stolen :). And honestly I don’t really give a crap I don’t have too many qualms about using code myself.

Today’s Mandalagaba would be very hard to reverse engineer, it’s way more complex, has more server components, and the client code is more obfuscated. In my opinion that’s how you retain control over your work, at least as a coder.

 

all out geekery, I.T. ben April 12, 2019

Protected: Nosy Monster… & Pals!

This content is password-protected. To view it, please enter the password below.

aesthetics, miscellaneous, web development ben March 16, 2019

I just have to post

This Dragon which found its way into the Mandalagaba digest. I haven’t seen anyone really touch recursion yet, and then this shows up.

This is my absolute favorite thing about adding features to Mandalagaba: seeing them used in ways I didn’t even realize were possible. Here recursion is used to create ethereal traits. Of course mirror symmetry is used for the face too but that I had seen before :). The hours spent hammering out recursion are all of a sudden, absolutely worth it.

The artist is here: https://www.instagram.com/laralaubert

I.T., web development ben March 07, 2019

Recursive Drawing is out

It’s only available on the “pro” facet of Mandalagaba. Oh yeah, Mandalagaba has been broken down into several facets for the purpose of simplifying and focusing activities.ย The facet where all the brain hurting stuff goes is the pro one. Pro is where one can draw a “radially symmetrical tessellation recursively”.

I tried to keep the menu simple and icon based but it’s still the most complex. Thankfully we have words to describe all that these things do.

Along with recursion, https://plant.mandalagaba.com is out too, using recursion, symmetries and a newly developed center placement to create plants & trees. This one still needs a bit of polish but the main idea is working. I touched a lot of the core engine of Mandagaba to introduce all this, development went pretty well. It was nice to test the flexibility I gave myself during last Winter’s rewrite for a major feature add.

 

aesthetics, web development ben March 03, 2019

A couple more for the road

Pretty fun, the result is less compelling than the experience of making them.

I.T., web development ben March 03, 2019

Getting there on recursion, there on recursion, on recursion, recursion

I still have a lot of details to figure out but I almost have recursion nailed. It’s a pretty brutal mental exercise to combine it with the existing radial symmetry & tessellations. As I’ve said before, one of the effects I seek in particular is that of a growing plant. In fact, I plan on dedicating a facet of Mandalagaba to guided drawing for just that. The adjustment of parameters which is very specific for getting a plant will be taken care of, and only the fun parts will remain. A perfect tool for the slacktivists who wants to feel like they’re helping greening up the world while staying glued to their screen.

I sometimes feel bad that so many people find stress, anxiety and even depression relief drawing mandalas on Mandalagaba. I feel like an enabler for giving them such a meaningless escape valve, on a screen at that. As much as I love a plant growing effect, I’m worried people will use it to get their virtual green fix while further removing themselves from nature. Get off your screens, grow an actual plant if you want to grow a virtual one.

I.T., maniacal paranoia ben February 12, 2019

Web Omnipresence with Docker, VPN & Squid proxying

Here’s a method for having several browser windows proxying through several countries concurrently.

Demo

[mejsvideo mp4=”http://ben.akrin.com/videos/omnipresence.mov.mp4″ ogg=”http://ben.akrin.com/videos/omnipresence.mov.ogv” webm=”http://ben.akrin.com/videos/omnipresence.mov.webm” poster=”http://ben.akrin.com/videos/omnipresence.mov.jpg” width=”640″ height=”360″]

Working Principle

Requirements

  • a VPN service supporting OpenVPN as a client (this example uses vpntunnel)
  • Docker
  • Firefox
  • MacOS isn’t a requirement per se but this guide & accompanying scripts are written for it.

Setup Steps

  1. Download this package containing Dockerfile build instructions & some scripts.
  2. Populate the directory “openvpn_config_files/” with the ovpn files from the VPN service you use.
  3. Edit the script called “vpn” and replace <VPN_SERVICE_USERNAME> and <VPN_SERVICE_PASSWORD> with your username and password.
  4. Run with “./omnipresence.sh <name_of_ovpn_file>”
aesthetics, I.T., web development ben January 15, 2019

Recursive Drawing Sneak Peek

I’ve been working on implementing recursive drawing into Mandalagaba. There are many, many tunables which can be implemented to facilitate recursive drawing. It’s tricky to pick the ones which make for a fun drawing experience. One of the effects that I seek in particular is that of a growing plant.

I.T., web development ben October 05, 2018

Flood fill #5

I just added a 5th HTML5 canvas flood fill algorithm which proposes a different method than filling pixel by pixel.

3D modeling / printing, I.T. ben September 25, 2018

Onetouch Delica 3D Printable Replacement Cap

Downloads

  • onetouch_lancing_device_replacement_cap.dae
  • onetouch_lancing_device_replacement_cap.stl

Story

We’ve gone through many of these and it’s always the same part that breaks:

Since the whole thing costs $20, I figured I’d build a 3D printable model of the dumb piece of plastic that is the cap.

After a few iterations, mass production time

And voila:

works like a charm.

aesthetics, all out geekery, I.T. ben September 11, 2018

Protected: Primitive

This content is password-protected. To view it, please enter the password below.

Posts pagination

← Previous 1 … 4 5 6 … 9 Next →

This blog is solar powered

Interactive

Handwriting Capture
Mandalagaba
IPv6 link-local to MAC converter
IPv6 MAC to link-local converter
Markov Text Generation
Markov Word Generation
Markov Music Generation
Duplogrifier
Flood Fill Algorithms
Homestead Metrics
RGB Playground
Web Games

Categories

  • aesthetics112
    • plots54
    • specular holography6
  • Books4
  • I.T.207
    • 3D modeling / printing21
    • AI7
    • all out geekery38
    • electronics29
    • homestead automation7
    • maniacal paranoia27
    • plotters49
    • unix / linux29
    • video games4
    • web development30
    • web games3
  • Lego / Duplo67
  • life in the U.S.42
  • miscellaneous205
  • nature encounters116
  • old vinyls3
  • organs2
  • self sustainability566
    • agriculture110
    • apiculture38
    • apple20
    • building132
    • canning3
    • crochet6
    • foraging6
    • hunting10
    • maple syrup47
    • poultry39
    • preserving3
    • solar power28
    • water23
    • wood85
  • trip to a new life6
Theme by Bloompixel. Proudly Powered by WordPress