Python – A Programing Language

Since the early 1990s, there has been a constant that is happening rapidly, at least on the consumer end. There were initially websites that were used. There were companies working on software on the outskirts. However, as the smartphone market grew, there was a lot going on. There was a lot of back and forth in order to automate the entire process of implementing and conceiving app features. App features that can provide recommendations based on acute data analysis are also available.

These systems could recommend products to you in the same way that your best friend could. Despite the fact that different programming languages were used for its implementation, Python became popular and is still one of the top contenders in the field of machine learning.

The language interpreters are available for a variety of operating systems. Python’s resources are managed and directed by a non-profit organisation known as the Python Software Foundation. Also, when we talk about development, it is done by a global community of developers. They maintain CPython, an open-source reference implementation of the Python programming language.

What are the reasons for its widespread acceptance?

👉 Simple to Use
Python syntax is quite simple, and Python has chosen to eliminate more trivial issues.
When compared to other languages, the language can save you a lot of lines. It is also highly effective and makes complex software development much easier.

👉 Broad Library and Framework Support
Python’s libraries and frameworks are one of the main reasons it is preferred over other languages. All of these can be used to help with development.

👉 Neural networks
It is a subset of machine learning with a distinct application. These learning systems are inspired by the brains of humans and animals. In this case, the machine learns by acquiring task-oriented rules. Image recognition is one of the best examples of this. Python provides a number of tools to assist you with this.

👉 Community and Support
There is no doubt that the language has strong support, as it is backed by one of the best tech companies, Google. Aside from that, there are numerous forums, websites, and video tutorials where Python is discussed and taught. This creates a much more welcoming environment in which the language can be taken seriously.

Growatt Inverter Client App – Java Client

Java Client for the Growatt Inverter

This Java application currently supports 3 main actions.

A1) Notify when the grid voltage is 0v (i.e. Power cut)

A2) Change power input priority (SUB / SBU)

A3) Change battery charging priority (Solar Only / Solar Priority)

A1) Notify when the grid voltage is 0v (i.e. Power cut).

Currently, the Growatt mobile app does not have any notification mechanism to alert when the grid power goes away. This app uses an ugly hack to achieve that up to some level.

The application keeps polling (once every 5 minutes) the Growatt cloud and checks if the Grid voltage is 0v. If it is, it fires a configured Gmail webhook which sends a chat message to the user. Since the Datalogger only uploads data once every 5 minutes, we can’t get an accuracy higher than 5 minites even if we change the app to run more frequently.

This will also send a power status chat every day at 7 AM to let you know that the app is running properly.

Note: Please don’t use this action unless you really need it, as this introduces considerable traffic to the Growatt cloud.

A2) Change power input priority (SUB / SBU)

This can be used to change power input priority of the inverter automatically, based on a time schedule.

This is written as a test case so that it can be automated using a Git Action workflow. Have a look at the Github workflow files in this repo.

A3) Change battery charging priority (Solar Only / Solar Priority)

This can be used to change the battery charging priority of the inverter automatically.

This is also written as a test case.

How to run?

  1. Configure authentication details in the Configurations.java file.
  2. To run #A1, build the repo and simply run the main method of the Monitor.java class.
  3. To run #A2 manually, you can use the below command.
mvn clean install -P change-settings -Dtest="MonitorTest#testOutputChangeToSUB"

or

mvn clean install -P change-settings -Dtest="MonitorTest#testOutputChangeToSBU"

To automate #A2, create a private git clone of this repo (as you’re configuring your credentials in step 1). Change cron jobs based on your requirement.

  1. To run #A3 manually, you can use the below command.
mvn clean install -P change-settings -Dtest="MonitorTest#testChargingChangeToSolarOnly"

or

mvn clean install -P change-settings -Dtest="MonitorTest#testChargingChangeToSolarPriority"

 

Special Thanks to bhathiya/growatt-inverter-client

Sako Isun Inverter USB Driver + Monitoring

This is an Solar inverter monitoring and controlling system for hybrid inverters, Following are the main components in the system.

  • Solar Inverter driver program to communicate with USB serial port (Python)
  • Python Flask based REST API to expose the data
  • ReactJS based web portal (PWA) for monitoring and controlling the inverter

Tested Solar inverters

Currently we have tested this on Sako Isun 3KW.

Supported compute devices

  • Raspberry pi
  • Orange pi
  • Any Unix device

Hardware setup

  • Use the USB cable provided with the inverter or any appropriate USB cable
  • Connect the USB cable to any of the supported device
  • Install the pre-requisite mentioned in the following install steps
  • Run the tools/check-inverter.py script to connection between inverter and the compute device
  • For any issues check the Troubleshoot section

How it works

Most of the Hybrid(Chinees) inverters comes with the following Serial interface

Bus 001 Device 002: ID 0665:5161 Cypress Semiconductor USB to Serial

For this VendorID and ProductID there are several UPS and inverter devices using this serial com device. But this device had no drivers for Raspberry pi, So when the inverter is connected to a Raspberry pi(or similar) compute device , it detects as a USB block storage device

/dev/usb/hiddev0

not as a USB serial communication device.

i:e

/dev/ttyS0 or /dev/USB0

To establish communication between the inverter and the compute device we had to use pyUSB approach described in here. For the basic working principles of Inverter – Compute device (Raspberry pi) communication check the above article.

Another important piece of the puzzle was to find out the communication protocol. This document from a random generous Czech inverter site.

Without this, Decoding the values sent from inverter was a challenge

and the meanings of

  • QPIGS: Device general status parameters inquiry

and

  • QMOD: Device Mode inquiry

were like greek!

Once the communication is established it’s was just a matter of routing the data to client application (React app) to present the data.

We use Flask to implement REST API and ReactJS, MUI , React Query in the UIs.

Install

Most of the Raspberry pi & Orange Pi variations doesn’t come with pip pre-installed, Hence we have to run this

  • sudo apt-get install python3-pip

Install the Python USB communication library

  • python3 -m pip install pyusb

This is required for the following crc16 library

  • sudo apt-get install python3-dev

CRC16 is used to generate the 2 byte CRC, CRC is a way of detecting accidental changes in data storage or transmission

| Note: This only works upto python 3.9 versions, If you have a latest version of Python 3.10+, This will not work

  • python3 -m pip install crc16

Add a Udev rule as shown below, This is required to allow communicating with the USB device for none-sudoers users. Example file is given in

references/99-knnect.rules

in this repo

  • sudo vim /etc/udev/rules.d/99-.rules

Restart the Udev admin to apply the changes

  • sudo udevadm control –reload-rules && sudo udevadm trigger

Accessing from anyway

Currently this only support monitoring through the local network, If you want to monitor or control the device through internet, Then you need to expose the APIs through Choreo (It’s free) like API proxy service or Buy a Blynk subscription and publish data to blynk.

Troubleshoot

  • Use
sudo lsusb

to check whether the Serial Communication device has been detected by the operating system if so it show show as

Bus 001 Device 002: ID 0665:5161 Cypress Semiconductor USB to Serial

in the output of lsusb command

Special Thanks To (tmkasun/solar-hybrid-inverter-monitor)

Electron Desktop App – Camera Access

Electron is a good application building platform for Desktops (Windows, Mac & Linux). It is very easy to access local PC resources like camera in a simple local HTML file.

In this main.js file we created a electron browser and load simple java script file preload.js to access camera stream and passed to html5 video element.

main.js

const {app, BrowserWindow} = require('electron');
const path = require('path');

let mainWindow;

// This method will be called when Electron has done everything
// initialization and ready for creating browser windows.
app.on('ready', function() {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 800, 
    height: 600, 
    webPreferences: {
      preload: path.join(__dirname, "preload.js")
    }
  });

  // and load the index.html of the app.
  mainWindow.loadFile('index.html');

  // Emitted when the window is closed.
  mainWindow.on('closed', function() {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;
  });
});


// Quit when all windows are closed.
app.on('window-all-closed', function() {
  if (process.platform != 'darwin')
    app.quit();
});

preload.js

navigator.mediaDevices.getUserMedia({video: true})
  .then(function(stream) {
    document.getElementById('camera').srcObject = stream;
  }).catch(function() {
    alert('could not connect stream');
  });

Download full source from here https://github.com/lahirutm/Electron-Camera-Access  and run

npm install

to install dependencies and libraries.

then

npm start

to run the sample. Then you camera stream will display in the desktop app made using Electron.

Desktop App using HTML, CSS & JavaScript

Electron is an open source library developed by GitHub for building cross-platform desktop applications with HTML, CSS, and JavaScript. Electron accomplishes this by combining Chromium and Node.js into a single runtime and apps can be packaged for Mac, Windows, and Linux.

Before proceeding with this tutorial, you should have a basic understanding of Javascript and HTML. You also need to know about a few native Node.js

Electron enables you to create desktop applications with pure JavaScript by providing a runtime with rich native APIs.

To get started with developing using the Electron, you need to have Node and npm installed.

First download sample app from this URL. https://github.com/lahirutm/electron-test-apps

According to the main.js file, we open index.html file in a electron browser window.

const { app, BrowserWindow, ipcMain } = require("electron");

let mainWindow;

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600
  });

  mainWindow.loadFile("index.html");
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
  createWindow();

  app.on("activate", function () {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on("window-all-closed", function () {
  if (process.platform !== "darwin") app.quit();
});

 

To run this app open a terminal & run below command to install dependencies & libraries.

npm install

then run this to start the example app.

npm start

Then example app will open.

NODE.JS SMPP Server & Client

Introduction

This is a complete implementation of SMPP v5.0 in node.js, with support for custom commands and TLVs.

SMPP v5.0, by design, is backward compatible with v3.4, so you would be able to use this module with 3.4 implementations. Even you can use this module with 3.3 implementations as far as you don’t use TLV parameters and don’t bind in transceiver mode.

The name of the methods and parameters in this implementation are equivalent to the names defined in SMPP specification. So get a copy of SMPP v5.0 Specification for a list of available operations and their parameters.

Creating a SMPP session

var smpp = require('smpp');
var session = smpp.connect({
	url: 'smpp://example.com:2775',
	auto_enquire_link_period: 10000,
	debug: true
}, function() {
	session.bind_transceiver({
		system_id: 'YOUR_SYSTEM_ID',
		password: 'YOUR_PASSWORD'
	}, function(pdu) {
		if (pdu.command_status === 0) {
			// Successfully bound
			session.submit_sm({
				destination_addr: 'DESTINATION NUMBER',
				short_message: 'Hello!'
			}, function(pdu) {
				if (pdu.command_status === 0) {
					// Message successfully sent
					console.log(pdu.message_id);
				}
			});
		}
	});
});

Creating a SMPP server

var smpp = require('smpp');
const utf8 = require('utf8');


var server = smpp.createServer(function(session) {

	console.log("\nIncoming session %s", session);

	session.on('bind_transceiver', function(pdu) {
		// we pause the session to prevent further incoming pdu events,
		// untill we authorize the session with some async operation.
		console.log("\nPDU bind_transceiver %s",pdu);
		session.pause();

		checkAsyncUserPass(pdu.system_id, pdu.password, function(err) {
			var system_id = pdu.system_id;
			console.log("\nAtemting to connect with system_id %s",system_id);

			if (err) {
				session.send(pdu.response({
					command_status: smpp.ESME_RBINDFAIL
				}));
				session.close();
				console.log("\nAuth Failed for id %s password %s \n",pdu.system_id,pdu.password);
				return;
			}
			session.send(pdu.response());
			session.resume();

			session.on('submit_sm', function(pdu) {
				var destination_addr = pdu.destination_addr;
				var short_message = pdu.short_message.message;
				if(pdu.message_payload && pdu.message_payload.length>0) {
					console.log("Payload %s \n",pdu.message_payload);
					if(pdu.message_payload.message) short_message = pdu.message_payload.message;
				}
				if(destination_addr && destination_addr.length==11 && destination_addr.substr(0,2)==="94"){
					if(short_message && short_message.length>0){
						destination_addr = "0" + destination_addr.substr(-9);

						let sms = utf8.decode(short_message);
						let char_count = sms.length;
						let no_of_sms = Math.ceil(char_count / 160);

						var msgid = "1234567890"; // generate a unique number here

						var message_id = msgid.padStart(10, '0');
						session.send(pdu.response({
							message_id: message_id
						}));

						if (pdu.registered_delivery) {
							send_delivery_reports(pdu, session, system_id, message_id);
						}

						console.log("\nSMS Sent, msg id %s",msgid);
						
					}
					else {
						console.log("\nInvalid message content %s \n", short_message);
					}
				}
				else {
					console.log("\nInvalid destination number %s \n", destination_addr);
				}

				console.log("\nPDU bind_transceiver :: submit_sm %s",pdu);
			});

			session.on('unbind', function(pdu) {
				session.send(pdu.response());
				session.close();
				console.log("\nPDU bind_transceiver :: unbind %s",pdu);
			});

			session.on('enquire_link', function(pdu) {
				session.send(pdu.response());
				console.log("\nPDU bind_transceiver :: enquire_link %s",pdu);
			});

			session.on('deliver_sm_resp', function(pdu) {
				console.log("\nPDU bind_transceiver :: deliver_sm_resp for %s \n %s",system_id, pdu);
			});
		});
	});

	session.on('bind_transmitter',function (pdu) {

		session.pause();
		checkAsyncUserPass(pdu.system_id, pdu.password, function(err) {
			var system_id = pdu.system_id;
			console.log("\nAtemting to connect with system_id %s",system_id);

			if (err) {
				session.send(pdu.response({
					command_status: smpp.ESME_RBINDFAIL
				}));
				session.close();
				console.log("\nAuth Failed for id %s password %s \n",pdu.system_id,pdu.password);
				return;
			}
			session.send(pdu.response());
			session.resume();


			session.on('submit_sm', function(pdu) {
				
				var destination_addr = pdu.destination_addr;
				var short_message = pdu.short_message.message;
				if(pdu.message_payload) {
					console.log("Payload %s \n",pdu.message_payload);
					if(pdu.message_payload.message) short_message = pdu.message_payload.message;
				}
				if(destination_addr && destination_addr.length==11 && destination_addr.substr(0,2)==="94"){
					if(short_message && short_message.length>0){
						destination_addr = "0" + destination_addr.substr(-9);

						let sms = utf8.decode(short_message);
						let char_count = sms.length;
						let no_of_sms = Math.ceil(char_count / 160);

						var msgid = "1234567890"; // generate a unique number here
						var message_id = msgid.padStart(10, '0');
						session.send(pdu.response({
							message_id: message_id
						}));

						if (pdu.registered_delivery) {
							send_delivery_reports(pdu, session, system_id, message_id);
						}

						console.log("\nSMS Sent, msg id %s",msgid);
					}
					else {
						console.log("Invalid message content %s \n", short_message);
					}
				}
				else {
					console.log("\nInvalid destination number %s \n", destination_addr);
				}

				console.log("\nPDU bind_transmitter :: submit_sm %s", pdu);
			});

			session.on('unbind', function(pdu) {
				session.send(pdu.response());
				session.close();

				console.log("\nPDU bind_transmitter :: unbind %s", pdu);
			});

			session.on('enquire_link', function(pdu) {
				session.send(pdu.response());
				
				console.log("\nPDU bind_transmitter :: enquire_link %s", pdu);
			});
		});

		console.log("\nPDU bind_transmitter %s",pdu);
	});

	session.on('bind_receiver',function (pdu) {
		
		session.pause();
		checkAsyncUserPass(pdu.system_id, pdu.password, function(err) {
			var system_id = pdu.system_id;
			console.log("\nAtemting to connect with system_id %s",system_id);

			if (err) {
				session.send(pdu.response({
					command_status: smpp.ESME_RBINDFAIL
				}));
				session.close();
				console.log("\nAuth Failed for id %s password %s \n",pdu.system_id,pdu.password);
				return;
			}
			session.send(pdu.response());
			session.resume();

			session.on('deliver_sm_resp', function(pdu) {
				
				console.log("\nPDU bind_receiver :: deliver_sm_resp %s", pdu);
			});

			session.on('unbind', function(pdu) {
				session.send(pdu.response());
				session.close();

				console.log("\nPDU bind_receiver :: unbind %s", pdu);
			});

			session.on('enquire_link', function(pdu) {
				session.send(pdu.response());

				console.log("\nPDU bind_receiver :: enquire_link %s", pdu);
			});
		});

		console.log("\nPDU bind_receiver %s",pdu);
	});
});
server.listen(2775);


function checkAsyncUserPass(system_id, password, callback) {

	// check & validate system_id and password from your authentication mechanism
	var err = false; // set false for testing

	if(err) {
		callback(1); // error
		console.log("\nLogin failed for system_id: %s", system_id);
	}
	else {
		callback(0); // no error
		console.log("\nUser %s successfully logged in.", system_id);
	}
}


function send_delivery_reports(pdu, session, system_id, message_id){
	
	var nsms = "" + 1;
	nsms = nsms.padStart(3, '0');

	var m = new Date();
	var c_year = "" + m.getFullYear();
	var c_month = "" + (m.getMonth()+1);
	var c_date = "" + m.getDate();
	var c_hour = "" + m.getHours();
	var c_minute = "" + m.getMinutes();
	var second = "" + m.getSeconds();

	var current_time = c_year+c_month+c_date+c_hour+c_minute+second;

	session.deliver_sm({
		esm_class: 4,
	    source_addr: pdu.destination_addr,
	    destination_addr: pdu.source_addr,
	    short_message: {
	    	message: 'id:'+message_id+' sub:'+nsms+' dlvrd:'+nsms+' submit date:'+current_time+' done date:'+current_time+' stat:DELIVRD err:0 text:@'
	    },
	    receipted_message_id: message_id,
	    user_message_reference: message_id
	});

	console.log("\nsend_delivery_report DELIVRD :: deliver_sm pdu sent for %s",system_id);
}

 

It’s very important to listen for session errors, not listening for error events will terminate the program.

Project is forked from: https://github.com/farhadi/node-smpp

To see the full source code and implementation guide, visit: https://github.com/lahirutm/node-smpp

CBC Encryption and Decryption | What is CBC?

CBC

Cipher Block Chaining (significantly known as CBC) is a mode of encryption used in block ciphers. It is an advanced form of block cipher encryption and also more secured when compared to ECB. This mode uses a random block of bytes known as Initialization Vector (IV) to ensure randomization of encryption. It is important to use IV only once to ensure security.

Encryption:

CBC is one of the most popularly used mode of encryption in AES. Unlike in ECB mode, in CBC mode, encryption of one block of plaintext is dependent on the previous block. Each block of plaintext is XORed with the previous block of ciphertext, for the first block it is XORed with IV(16 bytes) and then sent through the whitebox. So, change in one single byte changes the entire ciphertext. Hence, eavesdropper can’t attack the data easily.

 C[i] = E(Pt[i]  ^ C[i-1])
 C[1] = E(Pt[i] ^ IV)

Advantages over CBC:

Dependency of one block encryption over the previous one ensures that traces of similar data aren’t left behind, whereas in ECB, change in a byte changes only the corresponding block i.e encrypting 2 blocks that contain same plaintext gives the same ciphertext in ECB. This gives a pattern to the attacker whereas in CBC this doesn’t happen.

Decryption:

Decryption is just the reverse. Each block of ciphertext is sent through the whitebox and then XORed with the previous block of ciphertext to recover the plaintext. So, one need not decrypt the previous block to get the required block of plaintext.

Pt[i] = D(C[i]) ^ C[i-1]
Pt[1] = D(C[1]) ^ IV

Attacks possible:

IV reusing might lead to leakage of information regarding the first block of plaintext. However the rest are unaffected. It is also vulnerable to attacks like bit flipping attack, padding oracle attack etc.

ECB Encryption and Decryption | What is ECB?

ECB

What is ECB?

Electronic Code Book (or ECB) mode of encryption is the simplest of all the modes of encryption. This mode of encryption is the first one which was implemented under AES. But, later we’ll analyze the plus and the minus features of this mode because of which it’s popularity is reduced. Now, we’ll see how is ECB mode of encryption is applied to any of the above described data encryption algorithm.

How is the encryption done?

In this mode of encryption the plain text is divided into different blocks of equal block sizes. Then each block is encrypted in parallel.

As you can see the different blocks of the plain text are encrypted separately using any of the algorithms described above (Like AES, DES) The parallel encryption of each block is the basic essence of the ECB mode.

How is decryption done?

Similar to the encryption the cipher text is divided into different blocks depending upon the block size. Thus, decryption is done on each block, at the same time, using the algorithm with which it was encrypted.

Advantages of ECB

The advantage of ECB mode of encryption over others is that here each block is encrypted separately. Therefore, if any of the block goes corrupted it doesn’t affect the rest of the encryption. Also, because of this feature a multiprocessor can simultaneously encrypt different blocks thus saving time.

Disadvantages of ECB

The main disadvantage of ECB is that the similar part of the plain text are encrypted with the same key to the same cipher text. That is, if in block 1 the plain text character ‘e’ is encrypted as ‘f’ in block 2 also if there’s ‘e’ in the plain text it would be encrypted as ‘f’. Also, the blocks of cipher text can be rearranged which when decrypted would give deranged output which is undesirable.

Vulnerabilities of ECB

The most common attack on ECB is the “ECB byte at a time attack” which exploits the loophole in ECB encryption which would give the same cipher text when applied to the similar characters of plain text.

Basic AES-128-CBC/AES-256-CBC Encryption/Decryption with PHP

For AES-128-CBC Encryption/Decryption | PHP

To use CBC encryption, you also need to sort the $iv offset, as follows: AES-128-CBC encryption and decryption.

Here i used simple keys for the example, But Keys need to be generated using a cryptographically secure random number generator if you are using this in a production.

$iv = '1234567890123456'; // 16 byte
$key = '1234567890123456'; // 16 byte
function decode($str,$key,$iv)
{
    return openssl_decrypt(base64_decode($str),"AES-128-CBC",$key,OPENSSL_RAW_DATA, $iv);
}

function encode($str,$key,$iv)
{
     return base64_encode(openssl_encrypt($str,"AES-128-CBC",$key,OPENSSL_RAW_DATA, $iv));
}

echo "String: Hellow World !";
echo "<br/>Encrypted String: ";
echo encode("Hellow World !",$key,$iv);
echo "<br/>Decryped String: ";
echo decode("l3mMP/irpStRPTIfYsdZmg==",$key,$iv); 

OUT PUT

String: Hellow World !
Encrypted String: l3mMP/irpStRPTIfYsdZmg==
Decryped String: Hellow World !

 

 

For AES-256-CBC Encryption/Decryption | PHP

function encrypt_decrypt($action, $string) 
    {
        $output = false;
        $encrypt_method = "AES-256-CBC";
        $secret_key = '12345678901234561234567890123456'; // 32 byte
        $secret_iv = '1234567890123456'; // 16 byte $key = hash('sha256', $secret_key); $iv = substr(hash('sha256', $secret_iv), 0, 16); if ( $action == 'encrypt' ) { $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv); $output = base64_encode($output); } else if( $action == 'decrypt' ) { $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv); } return $output; } echo "String: Hellow World !"; echo "<br/>Encrypted String: "; echo encrypt_decrypt('encrypt', "Hellow World !"); echo "<br/>Decryped String: "; echo encrypt_decrypt('decrypt', "QkNZWjlab2pSTUtqVnMyMHlYeTV4dz09");

 

OUT PUT

String: Hellow World !
Encrypted String: QkNZWjlab2pSTUtqVnMyMHlYeTV4dz09
Decryped String: Hellow World !

Basic AES-128-ECB Encryption/Decryption with PHP

Note: ECB is useful for random data, but structured data should use a stronger mode like MCRYPT_MODE_CBC, Because ECB is an insecure method for sensitive data.

Lets see an example of its usage in PHP.

The Key must be 16bit long.

    $key = '1234567890123456';
   
    function encrypt($data,$key) {
        return base64_encode(openssl_encrypt($data, "aes-128-ecb", $key, OPENSSL_RAW_DATA));
    }

    function decrypt($data,$key) {
        return openssl_decrypt(base64_decode($data), "aes-128-ecb", $key, OPENSSL_RAW_DATA);
    }

 

To Encrypt, Simply call

$data = "This is to be encrypted";
echo $encrypted_text = encrypt($data,$key);

 

To Decrypt the above encrypted text

$data = "This is to be encrypted";
$encrypted_text = encrypt($data,$key);

$data = $encrypted_text;
echo $decrypted_text = decrypt($data,$key);

But there are other problems in this code which make it insecure, in particular the use of ECB (which is not an encryption mode, only a building block on top of which encryption modes can be defined).

Why ECB is insecure ?

You have a cipher, that with a key will encrypt 16 bytes of data. And you have some data, that is more than 16 bytes. Its a problem. ECB is the wrong solution to that problem: you just encrypt each 16-bytes block separately.

Why is it wrong? Because this way blocks that were equal before encryption will remain equal also after! And this will lead to all kinds of unwanted consequences.