{"id":1098,"date":"2018-04-05T13:00:03","date_gmt":"2018-04-05T12:00:03","guid":{"rendered":"http:\/\/chewett.co.uk\/blog\/?p=1098"},"modified":"2020-09-26T22:09:18","modified_gmt":"2020-09-26T21:09:18","slug":"raspberry-pi-cluster-node-06-sending-slave-details-to-the-master","status":"publish","type":"post","link":"https:\/\/chewett.co.uk\/blog\/1098\/raspberry-pi-cluster-node-06-sending-slave-details-to-the-master\/","title":{"rendered":"Raspberry Pi Cluster Node \u2013 06 Sending Slave Details to the Master"},"content":{"rendered":"\n<p>This post builds on&nbsp;<a href=\"https:\/\/chewett.co.uk\/blog\/1072\/raspberry-pi-cluster-node-05-talking-to-nodes-with-json\/\">my previous posts in the Raspberry Pi Cluster series<\/a>&nbsp;by changing how the slave sends messages. From now on the slave will send useful information about the system to the master. The master will also be configured to receive messages of many types.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Changing the message format<\/h2>\n\n\n\n<p>To start with I have coded it so that sending JSON messages between the nodes would print out the message. Now I am going to change it so that it can send different types of messages.<\/p>\n\n\n\n<p>To do this I am first going to change the format I use to send messages. To do this I am going to modify <code>create_msg_payload<\/code> function to be more useful.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><pre class=\"brush: python; title: ; notranslate\" title=\"\">def create_payload(payload, payload_type=\"message\"):\n    return json.dumps({\"type\": payload_type, \"payload\": payload}) + MESSAGE_SEPARATOR<\/pre><\/pre>\n\n\n\n<p>Here I have renamed the function and added a new parameter to the function, <code>payload_type<\/code>. This is currently set to default to the string <code>message<\/code>.<\/p>\n\n\n\n<p>The format I am using to send data has been changed to a more generic one with two keys, <code>type<\/code> and <code>payload<\/code>. This allows me to send a simple string or a more complex object if required. The master will handle each payload differently based on the string in the type field.<\/p>\n\n\n\n<p>Now I have a flexible system able to send any data and payload I require. I will talk about how the&nbsp;master can then handle each different type later.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Getting useful system information<\/h2>\n\n\n\n<p>To make the slave a little more interesting I am going to add a new type of payload, the <code>machine_details<\/code>&nbsp;payload. This is going to include a number of details about the slave to pass to the master.<\/p>\n\n\n\n<p>In the future I am going to use this information to judge what slaves should perform what tasks. This is important as certain tasks may require specific machine requirements, such as a minimum amount of system RAM.<\/p>\n\n\n\n<p>I am going to send the hostname, CPU&nbsp;percentage used, RAM, CPU type, and the number of CPU cores. To get this data I am going to use a number of different python libraries in the slave script. Below I import the required python libraries to send the data I want to the master.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><pre class=\"brush: python; title: ; notranslate\" title=\"\">import socket\nimport psutil\nimport platform\nimport multiprocessing<\/pre><\/pre>\n\n\n\n<p>Now I have these libraries I can create my object to send to the master.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><pre class=\"brush: python; title: ; notranslate\" title=\"\">machine_details = {\n    'hostname': socket.gethostname(),\n    'cpu_percent_used': psutil.cpu_percent(1),\n    'ram': psutil.virtual_memory().total,\n    'cpu': platform.processor(),\n    'cpu_cores': multiprocessing.cpu_count()\n}<\/pre><\/pre>\n\n\n\n<p>Above I have created the machine_details object that I will send across. I will detail what I am using for each section and what it returns below.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>hostname<\/code> &#8211; The <code>socket<\/code> library&nbsp;provides a very helpful method called <code>gethostname<\/code>. This returns the current hostname of the machine. This will be used later to assign a name to each slave.<\/li><li><code>cpu_percent_used<\/code> &#8211; The <code>psutil<\/code> module is a cross-platform module that deals with getting machine specific information. Here I am using the <code>cpu_percent<\/code> function telling it to wait 1 second averaging the CPU usage over that time period. This can be used to give a rough guide on how loaded the system is. This will prove useful when I am looking to balance the CPU&nbsp;load across a number of nodes.<\/li><li><code>ram<\/code> &#8211; <code>psutil<\/code> is again used to return the amount of RAM the system has available.<\/li><li><code>cpu<\/code> &#8211; Here I am using the <code>platform<\/code> library to return a string representing the type of CPU the machine has. This is a platform independent&nbsp;module but does not return any specific format. This is important to note as it depends what information the operating system can obtain about the CPU. Becuase of this reason I am going to use this as a display value only.<\/li><li><code>cpu_cores<\/code> &#8211; The <code>multiprocessing<\/code> library allows us to easily get the number of CPU&#8217;s the system has. Again this will be useful in the future to give a rough estimate of how parallel each machine can run tasks.<\/li><\/ul>\n\n\n\n<p>Now I have my object I can then send it to the master using&nbsp;the <code>create_payload<\/code> function as below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sock.send(create_payload(machine_details, 'machine_details'))<\/pre>\n\n\n\n<p>I use the key <code>machine_details<\/code> as the type so the master can handle this differently.&nbsp;Now I am going to change how the master handles the messages.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Handling different message types on the master<\/h2>\n\n\n\n<p>Now I am sending different types of messages I need to handle this on the master in some way. Since the type field determines the format of the payload we just need to handle it based on this.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><pre class=\"brush: python; title: ; notranslate\" title=\"\">message = get_message(clientsocket)\nif message:\n    if message&#x5B;'type'] == 'message':\n        logger.info(\"Received message: \" + message&#x5B;'payload'])\n    elif message&#x5B;'type'] == 'machine_details':\n        logger.info(\"Machine specifications: \" + json.dumps(message&#x5B;'payload']))\n    else:\n        logger.warning(\"Unknown payload type {type}, payload content {content}\".format(\n            type=message&#x5B;'type'], content=json.dumps(message&#x5B;'payload'])\n        ))<\/pre><\/pre>\n\n\n\n<p>In the above example I am using a simple <code>if<\/code> statement chain to handle the different types of payloads. I am using the same code as before to handle any messages received. If there is a type that I have not handled in the code, it will print out an error declaring it doesn&#8217;t understand the message.<\/p>\n\n\n\n<p>If I receive the message type machine_details I am json encoding and printing out the data received. In the future&nbsp;I will store this machine data and use it to allocate tasks.<\/p>\n\n\n\n<p>As further message types are added I will add more if statements here. In the future I will add a more generic solution for handling message types.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>Now I have modified the original data sending functions so it now uses a more generic format. This allows the master to read what messages are being received and determine what action it needs to take.<\/p>\n\n\n\n<p>I have a versatile system for receiving messages from a node and processing them so I will look into creating a two-way dialogue between the master and slave in the future.<\/p>\n\n\n\n<p>The full code is\u00a0<a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/chewett\/RaspberryPiCluster\/releases\/tag\/v6.0\" target=\"_blank\">available on Github<\/a>, any comments or qduestions can be raised there as issues or posted below.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This post builds on&nbsp;my previous posts in the Raspberry Pi Cluster series&nbsp;by changing how the slave sends messages. From now on the slave will send useful information about the system to the master. The master will also be configured to receive messages of many types.<\/p>\n","protected":false},"author":1,"featured_media":1104,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Today I wrote about improving my #RaspberryPi #Cluster so that each Slave node reports back the machine details and improved the messaging format.","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[122],"tags":[240,243,244,242,184,185,37,101],"class_list":["post-1098","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-raspberry-pi-cluster","tag-json","tag-multiprocessing","tag-platform","tag-psutil","tag-python","tag-rasbian","tag-raspberry-pi","tag-raspberry-pi-cluster"],"wppr_data":{"cwp_meta_box_check":"No"},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/03\/rpi_cluster_06_sending_slave_details_to_master.jpg?fit=800%2C800&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/p2toWX-hI","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":1072,"url":"https:\/\/chewett.co.uk\/blog\/1072\/raspberry-pi-cluster-node-05-talking-to-nodes-with-json\/","url_meta":{"origin":1098,"position":0},"title":"Raspberry Pi Cluster Node &#8211; 05 Talking to nodes with JSON","author":"Chewett","date":"March 21, 2018","format":false,"excerpt":"This post builds on my previous posts in the Raspberry Pi Cluster series by changing the format of the data I send. In this tutorial I am now sending data as JSON to allow a richer set of messages to be sent. Why use JSON to send data In previous\u00a0tutorials\u2026","rel":"","context":"In &quot;Raspberry Pi Cluster&quot;","block_context":{"text":"Raspberry Pi Cluster","link":"https:\/\/chewett.co.uk\/blog\/category\/raspberry-pi-cluster\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/03\/rpi_cluster_05_sending_with_json.jpg?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/03\/rpi_cluster_05_sending_with_json.jpg?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/03\/rpi_cluster_05_sending_with_json.jpg?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/03\/rpi_cluster_05_sending_with_json.jpg?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1781,"url":"https:\/\/chewett.co.uk\/blog\/1781\/raspberry-pi-cluster-node-07-sending-data-to-the-slave\/","url_meta":{"origin":1098,"position":1},"title":"Raspberry Pi Cluster Node \u2013 07 Sending data to the Slave","author":"Chewett","date":"December 5, 2018","format":false,"excerpt":"This post builds on\u00a0my previous posts in the Raspberry Pi Cluster series\u00a0by adding the ability to receive data from the master. In this\u00a0update, I will be adding a way\u00a0for the slave to request data and\u00a0have it returned by the master. Moving machine details into its own file The first thing\u2026","rel":"","context":"In &quot;Raspberry Pi Cluster&quot;","block_context":{"text":"Raspberry Pi Cluster","link":"https:\/\/chewett.co.uk\/blog\/category\/raspberry-pi-cluster\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/12\/rpi_cluster_07_sending_to_slave.jpg?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/12\/rpi_cluster_07_sending_to_slave.jpg?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/12\/rpi_cluster_07_sending_to_slave.jpg?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/12\/rpi_cluster_07_sending_to_slave.jpg?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1913,"url":"https:\/\/chewett.co.uk\/blog\/1913\/raspberry-pi-cluster-node-10-more-advanced-connection-handling\/","url_meta":{"origin":1098,"position":2},"title":"Raspberry Pi Cluster Node \u2013 10 More Advanced Connection Handling","author":"Chewett","date":"January 16, 2019","format":false,"excerpt":"This post builds on\u00a0my previous posts in the Raspberry Pi Cluster series\u00a0by improving the connection code so it wont crash when the master or slave disconnects. Using Exceptions to handle socket issues The improvements to the cluster code are going to add an exception to the communication code. This will\u2026","rel":"","context":"In &quot;Raspberry Pi Cluster&quot;","block_context":{"text":"Raspberry Pi Cluster","link":"https:\/\/chewett.co.uk\/blog\/category\/raspberry-pi-cluster\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2019\/01\/rpi_cluster_10_advanced_connection_handling.jpg?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2019\/01\/rpi_cluster_10_advanced_connection_handling.jpg?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2019\/01\/rpi_cluster_10_advanced_connection_handling.jpg?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2019\/01\/rpi_cluster_10_advanced_connection_handling.jpg?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":901,"url":"https:\/\/chewett.co.uk\/blog\/901\/raspberry-pi-cluster-node-03-basic-node-communication-two-nodes\/","url_meta":{"origin":1098,"position":3},"title":"Raspberry Pi Cluster Node \u2013 03 Basic node communication between two nodes","author":"Chewett","date":"December 9, 2017","format":false,"excerpt":"This post builds on the second step to create a Raspberry Pi Cluster Node to create a hello world application across two different scripts. Here we will create a socket connection between the two and use it to send a message to the master. Designing the client-master Raspberry Pi Nodes\u2026","rel":"","context":"In &quot;Raspberry Pi Cluster&quot;","block_context":{"text":"Raspberry Pi Cluster","link":"https:\/\/chewett.co.uk\/blog\/category\/raspberry-pi-cluster\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2017\/12\/rpi_cluster_03_basic_communication.jpg?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2017\/12\/rpi_cluster_03_basic_communication.jpg?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2017\/12\/rpi_cluster_03_basic_communication.jpg?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2017\/12\/rpi_cluster_03_basic_communication.jpg?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":2680,"url":"https:\/\/chewett.co.uk\/blog\/2680\/raspberry-pi-cluster-node-16-python-3-codebase-refactor\/","url_meta":{"origin":1098,"position":4},"title":"Raspberry Pi Cluster Node \u2013 16 Python 3 Codebase Refactor","author":"Chewett","date":"October 24, 2020","format":false,"excerpt":"This post builds on\u00a0my previous posts in the Raspberry Pi Cluster series\u00a0by improving the codebase for Python 3. Moving to Python 3 Python 2 was marked end of life on January 1st, 2020 and therefore applications should ideally be no longer using Python 2. There will still be a lot\u2026","rel":"","context":"In &quot;Raspberry Pi Cluster&quot;","block_context":{"text":"Raspberry Pi Cluster","link":"https:\/\/chewett.co.uk\/blog\/category\/raspberry-pi-cluster\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_python3refactor_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_python3refactor_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_python3refactor_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_python3refactor_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_python3refactor_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":741,"url":"https:\/\/chewett.co.uk\/blog\/741\/raspberry-pi-cluster-node-01-logging-liveness\/","url_meta":{"origin":1098,"position":5},"title":"Raspberry Pi Cluster Node &#8211; 01 Logging Liveness","author":"Chewett","date":"November 1, 2017","format":false,"excerpt":"This post describes how to make a simple python script that logs the node is alive every 10 seconds. Why we are going to log each node is alive As discussed in the previous post on Distributed Computing on the Raspberry Pi Cluster there will be many slaves and a\u2026","rel":"","context":"In &quot;Raspberry Pi Cluster&quot;","block_context":{"text":"Raspberry Pi Cluster","link":"https:\/\/chewett.co.uk\/blog\/category\/raspberry-pi-cluster\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2017\/10\/rpi_cluster_01_logging_liveness.jpg?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2017\/10\/rpi_cluster_01_logging_liveness.jpg?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2017\/10\/rpi_cluster_01_logging_liveness.jpg?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2017\/10\/rpi_cluster_01_logging_liveness.jpg?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/posts\/1098","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/comments?post=1098"}],"version-history":[{"count":8,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/posts\/1098\/revisions"}],"predecessor-version":[{"id":2655,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/posts\/1098\/revisions\/2655"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/media\/1104"}],"wp:attachment":[{"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/media?parent=1098"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/categories?post=1098"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/tags?post=1098"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}