Daniel Dvorkin

My take on WordPress and related geekery

Category: WordPress (Page 2 of 3)

Photo1

Arduino controlled HTML5 Etch-a-Sketch using Node.js and Websockets

Oh boy, a lot of linkbait keywords in there.

I’ve been waiting for a bit of free time to implement a pice of software that takes a black and white bitmap and moves two stepper motors to make a real Etch-a-Sketch draw the bitmap content. Kinda what this guy did.

But in the mean time, I though it’d be fun to implement this the other way around, which is significantly easier and faster to do. Use two potentiometers connected to the Arduino to control a virtual Etch-a-Sketch. This weekend I sat down to do it, and put myself a limit of one hour. For the computer side my plan was to do something I have experience doing, a Python based GUI using wxpython.

But once I had the Arduino side working as I wanted, it struck me: Why not use this opportunity to do it in a technology I’ve been wanting to have an excuse to play with? First I went for Clojure, but that was almost too easy, so 80% in I decided to grow the scope a bit. I ended up implementing a really simple Node.js app that will read the serial port and pass the data collected from the Arduino to the front-end jQuery via a Websocket, and there use a canvas to make the drawings.

Clone the whole project on GitHub.

Arduino

The Arduino side is really simple. Two potentiometers connected to two different analog inputs (the signal pin), 5v and GND. On my first pass I was getting a lot of noise in the readings, which I tried to solve on the software side, but the results were pretty bad, so I added two 0.1 uF capacitors. You need to connect the capacitors between GND and the signal pin. This, plus a small threshold for computing the readings, works like a charm.

And the code:

/* threshold to keep the noise down */
const int TOLERANCE  = 5;
/* Pin definitions */
int horizontalPot = A0;
int verticalPot   = A1;
/* Global values for the pot's values */
int horizontalVal = 0;
int verticalVal   = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {

  int valX = analogRead( horizontalPot );    // read the value from the sensor 0
  int valY = analogRead( verticalPot );    // read the value from the sensor 1

  bool changed_or_new_X = abs ( valX - horizontalVal ) >= TOLERANCE || ( valX == 0 && horizontalVal != 0 )  || ( valX == 1023 && horizontalVal != 1023 );
  bool changed_or_new_Y = abs ( valY - verticalVal   ) >= TOLERANCE || ( valY == 0 && verticalVal != 0 )    || ( valY == 1023 && verticalVal   != 1023 );

  if ( changed_or_new_X || changed_or_new_Y ) {

    int invertedX = abs( 1024 - valX );
    int invertedY = abs( 1024 - valY );

    Serial.print( invertedX );
    Serial.print( "," );
    Serial.println( invertedY );
    horizontalVal = valX;
    verticalVal = valY;
  }

  delay(3);
}

Node.js

I’m posting the code here just for completion, but you’ll probably want to actually clone it and play with it.

Be aware that this is my first Node.js code ever, so please let me know in the comments if I’m doing something stupid.

Modules:

npm install serialport socket.io express

Main app:

var fs = require( "fs" );
var url = require( "url" );

/* Create the server in the port 9000 */
var http = require( "http" ).createServer(function ( req, res ) {
		var request = url.parse( req.url, false );
		var filename = request.pathname;

		if ( filename == "/" )
			filename = "/index.html";

		/* Append the frontend folder */
		filename = 'frontend' + filename;

		fs.readFile( filename, function ( err, data ) {
			/* Any error on reading the file? */
			if ( err ) {
				if ( err.errno == 34 )  // File not found
					res.writeHead( 404 );
				else
					res.writeHead( 500 );
				res.end();
				return;
			}

			res.writeHead( 200 );
			res.write( data );
			res.end();
		} );
	}
).listen( 9000 );

var io = require( "socket.io" ).listen( http );

io.set('log level', 1);

io.sockets.on( "connection", function ( socket ) {
	// On a new Socket.io connection, load the data provider we want. For now, just Arduino.
	var $provider = require( './providers/arduino.js' ).init( socket );
} );

./providers/arduino.js:

var serial = require( "serialport" );
var SerialPort = serial.SerialPort;

// Replace with the device name in your machine.
var portName = "/dev/cu.usbmodem1421";

var sp = new SerialPort( portName, {
	baudrate:9600,
	parser  :serial.parsers.readline( "\n" )
} );

module.exports = {

	init:function ( socket ) {

		/* When we get a new line from the arduino, send it to the browser via this socket */
		sp.on( "data", function ( data ) {
			console.log( data );
			socket.emit( "message", data.toString() );
		} );

	}

};

frontend/index.html


	Semi Virtual Etch-a-Sketch

<script type="text/<span class=">// <![CDATA[
// <![<span class="hiddenSpellError" pre="">CDATA</span>[
// ]]></script>
// <![<span class="hiddenSpellError" pre="">CDATA</span>[
// ]]></script>
javascript" src="http://code.jquery.com/jquery.min.js">
// ]]><script type="text/javascript">// <![CDATA[
// <![<span class="hiddenSpellError" pre="">CDATA</span>[
// ]]></script>
src</span>="/socket.io/socket.io.js">
// ]]></script>
<script type="text/javascript" src="scripts.js"></script></pre>
<div id="wrapper">
<div id="left"></div>
<div id="middle_wrapper">
<div id="top"></div>
<canvas id="sketch" width="523" height="346"></canvas>
<div id="bottom"></div>
</div>
<div id="right"></div>
</div>
<pre>

frontend/scripts.js

jQuery( document ).ready( function () {
		var $sketch = $( "#sketch" );
		var $context = $sketch[0].getContext( '2d' );

		var $lastX = -1;
		var $lastY = -1;

		var socket = io.connect( "/", {
			"reconnect"                :true,
			"reconnection delay"       :500,
			"max reconnection attempts":10
		} );

		socket.on( "message", function ( data ) {

			data = process_data( data );

			/* Initial position */
			if ( $lastX == -1 ) {
				$lastX = data.x;
				$lastY = data.y;
			}

			$context.moveTo( $lastX, $lastY );
			$context.lineTo( data.x, data.y );

			$lastX = data.x;
			$lastY = data.y;

			$context.strokeStyle = "#000";
			$context.stroke();

		} );

		function process_data( data ) {

			var ret = {
				x:0,
				y:0
			};

			var array = data.split( ',' );

			if ( array.length < 2 )
				return ret;

			ret.x = array[0];
			ret.y = array[1];

			ret = sanitize_size( ret );

			return ret;
		}

		/* Convert pot values to pixel using the canvas size ratio. */
		function sanitize_size( values ) {
			var max_pot = 1024;
			var max_canvas_x = 523;
			var max_canvas_y = 346;

			values.x = values.x * ( max_canvas_x / max_pot );
			values.y = values.y * ( max_canvas_y / max_pot );

			return values;
		}

	}
);

Result

(Disclaimer: I suck at drawing.)

waldo

bbPress Search

I’ve posted in Modern Tribe‘s blog a summary of what we discussed in the last bbPress dev chat about search. Go read and let me know what do you think.

There was an interesting discussion during the last bbPress dev meeting about the different approaches for implementing a solid search feature for the forums, and how it should play along with the general WordPress search. Here’s the main ticket. I’d like to keep the dialog going and will summarize the core ideas.I’m writing this without reviewing the whole chat and didn’t take notes, so… sorry in advance if I’m missing someone’s opinion or idea. Please do let me know in the comments. Continue reading….

IMG_0858

Our best product so far

I have neglected this blog for about two months because my wife and I were busy launching our best product so far.

Meet Maite. Forget about beta versions and release candidates. She’s incredible awesome, even without unit testing or -more importantly- user documentation.

I hate people giving parenting advice or suddenly becoming experts when they become parents. And I won’t bore you explaining (and documenting with a shitload of pictures and videos) why my kid is much prettier, smarter and lovelier than all other kids (although she clearly is). I’ll only say this: Becoming a parent is an incredible humbling experience, and I’m still surprised about how much it can shake your views on life and priorities.

holding the key

Take ownership of a WordPress database

One of the gigs that used to put food on my table was as WPML‘s support manager. Customers that needed help usually ended up sending me a DB dump so I could implement a local copy to reproduce the problem and test whatever their issue might be.

Tired of doing the repetitive task of updating the site url in wp_options table, changing all the urls in the wp_posts table, and changing the password for the admin user, I came up with this little script that will do that for me.

It needs to be said: Be careful of not uploading this script to a live server.


<?php

// Bad, bad things WILL happen if you forget to delete this file when you upload the site to a public server
// Did I say bad already?

// Load WordPress environment
require_once( dirname(__FILE__) . '/wp-load.php' );

// First I want to get access. Changing all administrator passwords to "admin". Go read the first comment of this code!
$wp_user_search = new WP_User_Query( array( 'role' => 'administrator' ) );
$admins = $wp_user_search->get_results();

foreach ($admins as $admin){
    wp_set_password('admin',$admin->ID);
}

// Now lets fix the Site URL and Home URL
// But first let's save the current siteurl, for later use.
$old_siteurl = get_option("siteurl");

$pageURL = 'http';
if (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
$pageURL .= "://";
if ($_SERVER["SERVER_PORT"] != "80") {
 $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
} else {
 $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
$new_siteurl = substr($pageURL,0,strrpos($pageURL,"/"));

update_option("siteurl", $new_siteurl);
update_option("home", $new_siteurl);

//And now those pesky hardcoded permalinks

$wpdb->query(
 "UPDATE $wpdb->posts SET guid = replace(guid, '{$old_siteurl}','{$new_siteurl}'); "
);

// Last but not least, those hardcoded urls (links, images, etc) in the posts contents

$wpdb->query(
 "UPDATE $wpdb->posts SET post_content = replace(post_content, '{$old_siteurl}','{$new_siteurl}');"
);

?>

Just drop this file in any WordPress installation and execute it on the browser.

221581cox1j1ytk

Bash script to backup all your MySQL databases

Backing up all your MySQL databases one by one is a pain. Here is a small bash script I made to dump and compress all my databases to my Dropbox folder.

  • The script will skip any database whose name starts with an underscore, so I can have test or junk databases that I don’t want to back up.
  • Every time it runs, it’ll delete all the previous backups (I don’t care, but if you do then just comment out line 7)
  • You need to change lines 3, 4 and 5 to reflect your MySQL user, password and folder where you want to put the dumps.
#!/bin/bash

USER="your_user"
PASSWORD="your_password"
OUTPUT="/Users/rabino/DBs"

rm "$OUTPUT/*gz" > /dev/null 2>&1

databases=`mysql --user=$USER --password=$PASSWORD -e "SHOW DATABASES;" | tr -d "| " | grep -v Database`

for db in $databases; do
    if [[ "$db" != "information_schema" ]] && [[ "$db" != _* ]] ; then
        echo "Dumping database: $db"
        mysqldump --force --opt --user=$USER --password=$PASSWORD --databases $db > $OUTPUT/`date +%Y%m%d`.$db.sql
        gzip $OUTPUT/`date +%Y%m%d`.$db.sql
    fi
done

Now you just need to make it executable:

chmod 700 backup.sh

And then add it to the crontab so it’ll run automagically:

crontab -e
00 20 * * * /path/to/backup.sh

In this case it’ll run every day at 8 PM. You can learn more about crontab here.

iStock_LaptopBeach

WordPress XML-RPC Helper Class

I found myself copying and pasting quite often the necessary code to make WordPress XML-RPC work. And what do we nerds do in those situations? Abstract!

This helper class will take the burden off of you. I’ll post the whole code here, and then explain each part.

abstract class MZAXMLRPC {
	protected $calls = Array();
	protected $namespace = "myxmlrpc";

	function __construct( $namespace ) {
		$this->namespace = $namespace;
		$reflector       = new ReflectionClass( $this );
		foreach ( $reflector->getMethods( ReflectionMethod::IS_PUBLIC ) as $method ) {
			if ( $method->isUserDefined() && $method->getDeclaringClass()->name != get_class() ) {
				$this->calls[] = $method->name;
			}
		}
		add_filter( 'xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
	}

	public function xmlrpc_methods( $methods ) {
		foreach ( $this->calls as $call ) {
			$methods[$this->namespace . "." . $call] = array( $this, "dispatch" );
		}
		return $methods;
	}

	public function dispatch( $args ) {
		global $wp_xmlrpc_server;

		$username = $args[1];
		$password = $args[2];
		$data     = $args[3];

		if ( !$wp_xmlrpc_server->login( $username, $password ) ) return $wp_xmlrpc_server->error;

		$call = $this->get_called_method();

		if ( method_exists( $this, $call ) ) {
			$status = call_user_func_array( array( $this, $call ), array( $data ) );
			return $status;
		} else {
			return "Method not allowed";
		}

	}

	private function get_called_method() {
		global $wp_xmlrpc_server;
		$call   = $wp_xmlrpc_server->message->methodName;
		$pieces = explode( ".", $call );
		return $pieces[1];
	}

}

This is an abstract class. You won’t instantiate objects out of it. What you’ll do is create a new class that inherits from MZAXMLRPC, and in it you’ll make public methods for each XML-RPC call you want to expose. I’ll post an example in a moment, but first let’s break this code into parts.

The constructor uses Reflection to find all the user-defined public methods of the child class that is inheriting from it. Then it will tell WordPress that we’re accepting XML-RPC calls for this methods. The XML-RPC methods are exposed with the name $namespace.$public_method_name.

All those new XML-RPC will arrive to the same method, dispatch. It will first validate the user/pass for the remote call, then it will check that effectively there is a method declared to take care of the XML-RPC call. If all validates ok it will dispatch the call to the appropriate method of the child class, passing along all the data that came through the XML-RPC server.

Enough gibberish already! The only thing you need to do is:

class MY_XMLRPC extends MZAXMLRPC {

	public function QuoteUpload( $data ) {

		if ( !isset( $data["author"] ) ) return "Missing 'author' parameter";

		if ( !isset( $data["quote"] ) ) return "Missing 'quote' parameter";

		$author = $data["author"];
		$quote  = $data["quote"];

		$new_post = array( 'post_status' => 'publish',
		                   'post_type'   => 'mzaquotes',
		                   'post_title'  => $quote );

		$new_post_id = wp_insert_post( $new_post );
		wp_set_post_terms( $new_post_id, $author, 'quote_author' );

		return "OK";
	}
}

new MY_XMLRPC( 'my_function' );

This little piece of code will expose a XML-RPC method called my_function.QuoteUpload. The parent class will deal with authentication and WordPress XML-RPC APIs for you.

Page 2 of 3

Powered by WordPress & Theme by Anders Norén