Hướng dẫn tạo chatbot đơn giản, dùng Node.js và Wit.ia

Xin chào! Tôi là Agitech Luân, hôm nay tôi sẽ hướng dẫn các bạn tạo chatbot đơn giản cho Fanpage Facebook của mình. Ngôn ngữ lập trình Node.js và sử dụng Wit.ia để hỗ trợ phân tích ngôn ngữ tự nhiên. Bắt đầu thôi!

MỘT SỐ YÊU CẦU BAN ĐẦU

1. Bạn phải có Facebook cá nhân và Fanpage, tất nhiên là fanpage mà bạn muốn tạo chatbot.

2. Bạn phải có tài khoản Glitch (glitch.com). Chúng ta sẽ code trên Glitch, đơn giản là vì mỗi 1 project của chúng ta được Glitch phân 1 tên miền server riêng.

CÁCH THỨC THỰC HIỆN

1. Truy cập vào https://glitch.com/edit/#!/agitech-chatbot và làm theo hướng dẫn

anh 3

Sau bước này chúng ta đã có được Source code.

Tại file .env chúng ta đang thiếu 4 token, tôi sẽ hướng dẫn bạn thiếp lập và lấy các token nhé.

anh 4

FB_PAGE_TOKEN

1. Truy cập vào https://developer.facebook.com/  => Ứng dụng của tôi => Tạo project

2. Tại menu làm theo hướng đẫn

anh 1

3. Thiếp lập Messenger

anh 2

FB_VERIFY_TOKEN, mình sẽ đặt là 123456, bạn có thể tự đặt lại token này

4. Thiết lập Webhook

anh 5

Đây là cách lấy URL gọi lại. Lưu ý: Phía sau URL gọi lại các bạn cần thêm "/webhook".

anh 6

FB_APP_SECRET

anh 7

Đến đây chúng ta còn thiếu mỗi WIT_TOKEN, các bạn tiếp tục

5. Truy cập vào https://wit.ai/ => Tạo App, có thể chọn thiếp lập là Tiếng Việt. Các bạn lấy token như hình nhé

anh 9

 

Đến đây coi như là sắp hoàn thành, bạn tự điền các TOKEN nhé. Đến phần "Dạy học" nào!!!

Lưu ý: Các bạn điền hết tất cả 4 token rồi mới thiết lập Webhooks nhé!

6. Dạy cho Wit những câu đơn giản

Bất đầu bằng 1 câu mang ý nghĩa đơn giản nhé, như câu "Xin chào ạ".

anh 8

Intent là biến ý nghĩa, ý muốn của câu. Khi người dùng chat "Xin chào" wit sẽ hiểu là "chào hỏi" (chao_hoi).

Đến với câu tiếp theo, chúng ta sẽ dạy bot câu có chứa thực thể. Ví dụ như "Xin chào chatbot" và "Xin chào admin", ở đây 2 câu điều mang ý nghĩa chào hỏi (chao_hoi) nhưng lại chứa thực thể "chatbot" và "admin". Chúng ta sẽ dạy wit như sau.

anh 10

Đối với câu "Xin chào admin", các bạn làm tương tự nhé!

Và chúng ta tận hưởng thành quả. Chúc các bạn thành công!!!

anh 11

 

 

Lập trình PHP kết hợp JS cho xem file PDF dưới dạng hình ảnh mà không bị lộ đường dẫn file PDF

php and js

Hôm nay, mình sẽ giới thiệu với các bạn một cách kết hợp PHP và JS để viết một trang Web xem nội dung file PDF dưới dạng hình ảnh, mà người truy cập không thể tải file PDF về máy tính. Cách này mình lấy ý tưởng từ PDF JS và mình đã kết hợp PHP vào để thực hiện trong một dự án gần đây.

Trước tiên bạn cần đưa thư viện PDF JS vào thẻ <head> của trang và đoạn CSS định dạng thêm đường viền cho hình nội dung cho dễ nhìn.

<script src="//mozilla.github.io/pdf.js/build/pdf.js"></script>
<style type="text/css">
	#the-canvas {
		border: 1px solid black;
		direction: ltr;
	}
</style>

Tiếp theo bạn xây dựng một bố cục phân trang và đánh số trang xem. Trong đoạn code sau tôi có dùng Class trong thư viện Bootstrap.

<div style="padding: 5px 10px 10px 10px;">
	<button class="btn btn-primary btn-rounded" id="prev">Trang trước</button>
	<button class="btn btn-primary btn-rounded" id="next">Trang sau</button>
	&nbsp; &nbsp;
	<span>Trang: <input id="page_num" value="" onchange="onOfPage(this);" style="width: 40px; text-align: right;"/> / <span id="page_count"></span></span>
</div>
<canvas id="the-canvas"></canvas>

Sau cùng bạn thêm đoạn code sau, đoạn code dùng PHP đọc nội dung file đưa vào JS để hiển thị vào thẻ <canvas> và phân trang.

<?php
	//Khai báo biến lấy nội dung file và encode base64
	$getPDF = base64_encode(file_get_contents('example.pdf'));
?>
<script type="text/javascript">
	var pdfData = atob('<?php echo $getPDF; ?>');
	
	var pdfjsLib = window['pdfjs-dist/build/pdf'];
	
	pdfjsLib.GlobalWorkerOptions.workerSrc = "//mozilla.github.io/pdf.js/build/pdf.worker.js";

	var pdfDoc = null,
		pageNum = 1,
		pageRendering = false,
		pageNumPending = null,
		scale = 1.2,
		canvas = document.getElementById('the-canvas'),
		ctx = canvas.getContext('2d');
	canvas.oncontextmenu = function() {return false};
	var loadingTask = pdfjsLib.getDocument({data: pdfData});
	loadingTask.promise.then(function(pdf) {
		pdfDoc = pdf;
		document.getElementById('page_count').textContent = pdf.numPages;
		renderPage(pageNum);
	}, function (reason) {
		console.error(reason);
	});
	
	function renderPage(num) {
		pageRendering = true;
		pdfDoc.getPage(num).then(function(page) {
			var viewport = page.getViewport({scale: scale});
			canvas.height = viewport.height;
			canvas.width = viewport.width;
			var renderContext = {
				canvasContext: ctx,
				viewport: viewport
			};
			var renderTask = page.render(renderContext);
			renderTask.promise.then(function() {
				pageRendering = false;
				if (pageNumPending !== null) {
					renderPage(pageNumPending);
					pageNumPending = null;
				}
			});
		});
		document.getElementById('page_num').value = num;
	}
	
	function queueRenderPage(num) {
		if (pageRendering)
			pageNumPending = num;
		else
			renderPage(num);
	}
	
	function onPrevPage() {
		if(pageNum <= 1)
			return;
		pageNum--;
		queueRenderPage(pageNum);
	}
	document.getElementById('prev').addEventListener('click', onPrevPage);

	function onNextPage() {
		if (pageNum >= pdfDoc.numPages)
			return;
		pageNum++;
		queueRenderPage(pageNum);
	}
	document.getElementById('next').addEventListener('click', onNextPage);

	function onOfPage(e) {
		var num = parseInt(e.value);
		if(Number.isInteger(num) == false)
			return;
		if(num > pdfDoc.numPages || num < 1)
			return;
		pageNum = num;
		queueRenderPage(pageNum);
	}
</script>

Tới đây trang của bạn có thể hiển thị nội dung của file PDF dưới dạng hình ảnh rồi.

Ngoài ra, bạn cũng có thể thêm đoạn code oncontextmenu="return false;" vào thẻ <body> để chặn người xem tải nội dung file hình về máy tính.

Bạn nào cảm thấy bài viết này hay thì hãy chia sẻ cho những bạn khác cần đến nhé. Chúc các bạn thành công!

Ngụy Kim Hưng

Dùng ESP8266 gửi dữ liệu cảm biến AM2315 qua giao thức HTTPS với data kiểu Json

esp8266 and am2315 post json data json

Hôm nay, tôi sẽ giới thiệu với các bạn cách dùng ESP8266 gửi dữ liệu cảm biến AM2315 (cảm biến nhiệt độ và độ ẩm) qua giao thức HTTPS với data kiểu Json.

Có thể một số đọc giả đã thực hiện vấn đề này rồi, bài viết này tôi chia sẻ cho những bạn mới tìm hiểu. Nếu bài viết có hay hãy chia sẻ cho người đang cần.

Quy trình thực hiện:

Bước 1: Cấm dây kết nối cảm biến ESP8266 với cảm biến AM2315.

Cảm biến AM2315 có 4 dây, các bạn cấm tương ứng với các màu như sau:

- Màu đỏ: cấm vào chân 5V (VCC).

- Màu đen: cấm vào chân GND.

- Màu trắng: cấm vào chân SCL.

- Màu vàng: cấm vào chân SDA.

Bước 2: Lập trình nạp code cho ESP8266.

Trong đoạn code sau mình đã lập trình mẫu sẵn và ghi chú đầy đủ các bước khai báo thư viện, khởi tạo biến và các hàm xử lý dữ liệu thành Json.

Các bạn chỉ cần lưu ý một vấn đề. Để kết nối với giao thức HTTPS bạn cần cấp khóa SHA-1.

Để lấy khóa SHA-1 các bạn vào trình duyệt thực hiện theo các bước như hình sau:

chon xem them thong tin chung chiChọn xem thêm thông tin bảo mật

chon xem chung chiChọn xem thông tin chứng chỉ SSL

lay khoa sha1Lấy thông tin SHA-1

Mỗi tên miền sẽ có chứng chỉ SSL khác nhau nên SHA-1 cũng khác nhau và các bạn lưu ý cập nhật SHA-1 khi chứng chỉ hết hạn được thay thế một chứng chỉ khác.

Các bạn cũng có thể đọc dữ liệu từ một link khác lấy và gán biến số cho SHA-1 để thay đổi tùy ý mà không cần nạp code lại.

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <Adafruit_AM2315.h>
#include <Wire.h>
#include <ArduinoJson.h>
#include <WiFiClientSecureBearSSL.h>
char ssid[] = "WiFi"; //Tên WiFi
char pass[] = "*******"; //Mật khẩu WiFi
unsigned long interval = 300000; //Cài đặt tham số thời gian lấy và gửi dữ liệu - đơn vị tính millis
unsigned long previousMillis = 0; //Cài đặt tham số mốc thời gian bắt đầu.

Adafruit_AM2315 am2315;
ESP8266WiFiMulti WiFiMulti;

void setup() {
	Serial.begin(9600);  
	WiFi.mode(WIFI_STA);
	WiFiMulti.addAP(ssid, pass);
	if (! am2315.begin()) {
		Serial.println("Sensor not found, check wiring & pullups!");
		while (1);
	}  
	Serial.println("Setup ok");
}

void loop() {
	unsigned long currentMillis = millis(); //Lấy mốc thời gian hiện tại
	//Kiểm tra thời gian bắt đầu board hoạt động đến hiện tại cho phép lấy và gửi dữ liệu
	if ((unsigned long)(currentMillis - previousMillis) >= interval)
	{
		previousMillis = currentMillis; //Gán lại mốc thời gian bắt đầu
		float temperature, humidity; //Khai báo tham số đo nhiệt độ và độ ẩm
		//Thực hiện đọc dữ liệu liệu đo nhiệt độ và độ ẩm
		if (! am2315.readTemperatureAndHumidity(&temperature, &humidity)) {
			Serial.println("Failed to read data from AM2315");
			return;
		}
		//Kiểm tra kết nối mạng WiFi
		if ((WiFiMulti.run() == WL_CONNECTED)) {  
			HTTPClient https;
			String link = "https://agitech.com.vn";
			//Tạo dữ liệu kiểu Json cho nhiệt độ và độ ẩm
			DynamicJsonDocument root(1024);
			root["nhietdo"] = temperature;
			root["doam"] = humidity;
			char json_str[100];
			serializeJsonPretty(root, json_str);
			//Kết thúc tạo Json kết quả sẽ như {"nhietdo": 30, "doam": 76}
			
			//Kết nối truy cập https với khóa SHA-1
			if(https.begin(link,"B6:EE:32:4E:28:89:8D:9A:76:D1:B7:6E:5C:D5:F6:4C:0A:7C:1D:73"))
			{
				https.addHeader("Content-Type", "application/json"); //Set header Content-Type kiểu Json
				int getlink = https.POST(json_str); //Gửi giữ liệu
				if (getlink > 0)
				{
					//Thực hiện gửi thành công và lấy dữ liệu trả về
					Serial.printf("[HTTPS] GET... code: %d\n", getlink);
					if (getlink == HTTP_CODE_OK || getlink == HTTP_CODE_MOVED_PERMANENTLY) {
						String payload = https.getString();
						Serial.println(payload);
					}
				}
				else
				{
					//Thực hiện gửi thất bại và thông báo lỗi kết nối
					Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(getlink).c_str());
				}
				https.end(); //Ngắt kết nối
			}else {
				//Lỗi kết nối https
				Serial.printf("[HTTPS] Unable to connect\n");
			}
		}
	}
}

Chúc các bạn thành công!

Ngụy Kim Hưng

Lập trình php tạo Transparent Watermark Logo (hình logo mờ trong suốt) cho hình ảnh

Chào các bạn, hôm nay mình sẽ giới thiệu cho các bạn đang lập trình php nhưng chưa biết cách tạo hình logo mờ ẩn trên hình (Transparent Watermark Logo).

Đoạn code php sau sẽ giúp các bạn tạo một logo mờ ẩn trên hình. Bạn có thể ứng dụng cho việc upload hình ảnh lên website và gắn logo bản quyền cho hình ảnh đó. Đoạn code chỉ lấy ví dụ hình ảnh có type là image/jpeg nên nếu các bạn muốn thực hiện với type khác bạn hãy tìm hiểu thêm nhé.

// Cấu hình vị trí độ mờ
$horiz_position = 'left'; // center | left | right
$horiz_shift = '20'; //Khoảng cách pixel với tọa độ x
$vert_position = 'top'; // middle | top | bottom
$vert_shift = '20'; //Khoảng cách pixel với tọa độ y
$transparency = '50'; //Tính trong suốt của hình logo mờ
$picture = imagecreatefromjpeg('iot-agitech.jpg'); // Hình ảnh cần gắn logo mờ
$logo_watermark = imagecreatefrompng('logo-cnxag.png'); // Hình logo (chọn file png)

$pct = $transparency/100;
$w = imagesx($logo_watermark);
$h = imagesy($logo_watermark);

imageAlphaBlending($logo_watermark, false);
// Tìm pixel mờ nhất trong hình ảnh (pixel có giá trị alpha nhỏ nhất)
$minAlpha = 127;
for($x = 0; $x < $w; $x++) {
	for($y = 0; $y < $h; $y++) {
		$alpha = (imagecolorat($logo_watermark, $x, $y) >> 24) & 0xFF;
		if($alpha < $minAlpha) {
			$minAlpha = $alpha;
		}
	}
}

// Lặp qua các pixel hình ảnh và sửa đổi alpha cho từng pixel
for($x = 0; $x < $w; $x++) {
	for($y = 0; $y < $h; $y++) {
		$colorXY = imagecolorat($logo_watermark, $x, $y);
		$alpha = ($colorXY >> 24) & 0xFF;
		if($minAlpha !== 127) {
			$alpha = 127 + 127 * $pct * ($alpha - 127) / (127 - $minAlpha);
		} else {
			$alpha += 127 * $pct;
		}
		$alphaColorXY = imagecolorallocatealpha(
			$logo_watermark,
			($colorXY >> 16) & 0xFF,
			($colorXY >> 8) & 0xFF,
			$colorXY & 0xFF,
			$alpha
		);
		if(!imagesetpixel($logo_watermark, $x, $y, $alphaColorXY)) {
			return false;
		}
	}
}

$picture_width=imageSX($picture);
$picture_height=imageSY($picture);
$watermarkfile_width=imageSX($logo_watermark);
$watermarkfile_height=imageSY($logo_watermark);

// Lấy vị trí tọa độ x cho hình mờ
switch ($horiz_position) {
case 'center':
	$dest_x = ( $picture_width / 2 ) - ( $watermarkfile_width / 2 );
	break;
case 'left':
	$dest_x = $horiz_shift;
	break;
case 'right':
	$dest_x = $picture_width - $watermarkfile_width - $horiz_shift;
	break;
}

// Lấy vị trí tọa độ y cho hình mờ
switch ($vert_position) {
case 'middle':
	$dest_y = ( $picture_height / 2 ) - ( $watermarkfile_height / 2 );
	break;
case 'top':
	$dest_y = $vert_shift;
	break;
case 'bottom':
	$dest_y = $picture_height - $watermarkfile_height - $vert_shift;
	break;
}

// Dùng cho hình gif
// if($picture_fileType == 'gif') {
	// $tempimage = imagecreatetruecolor($picture_width, $picture_height);
	// imagecopy($tempimage, $picture, 0, 0, 0, 0, $picture_width, $picture_height);
	// $picture = $tempimage;
// }

imagecopy($picture, $logo_watermark, $dest_x, $dest_y, 0, 0, $watermarkfile_width, $watermarkfile_height);

header('Content-Type: image/png'); 
imagepng($picture);

Kết quả hình ảnh sẽ giống như sau:

tao logo mo an tren hinh

 

Mong là bài viết này sẽ giúp ít cho những bạn đang tìm hiểu và phát triển kỹ năng lập trình php, để viết ra chức năng ứng dụng hay hơn cho trang web của mình.

Chúc các bạn thành công!

Ngụy Kim Hưng

Hướng dẫn cách khôi phục cơ sở dữ liệu mysql khi lỡ xóa file ibdata

 khoi phuc mysql database

Nếu có một ngày bạn vô tình xóa (Shift + Delete) file ibdata của cơ sở dữ liệu Mysql, thì bạn cũng đừng quá lo lắng vì tôi cũng từng phạm phải trường hợp như bạn và thật mai mắn khi tôi tìm được một cách giải quyết.

Trong bài viết này tôi chia sẻ cho các bạn cách khôi phục mà tôi đã làm, mong là có thể giúp ích cho đọc giả khi đọc bài viết này.

Để có thể khôi phục trong thư mục data của Mysql bạn vẫn còn giữ thư mục các database, trong đó có file .frm và .ibd . Ngoài ra bạn vẫn cần có file .sql cũ để có thể Import lấy lại cấu trúc các bảng dữ liệu.

Khi truy cập vào cơ sở dữ liệu phpmyadmin bạn vẫn thấy database, table nhưng cấu trúc và dữ liệu đã bị mất, chọn vào bảng dữ liệu sẽ hiển thị lỗi "table doesn't exist".

Sau đây là các bước để thực hiện khôi phục dữ liệu:

Bước 1: Bạn tạo một database mới, rồi Import file .sql cũ vào.

Bước 2: Bạn khôi phục lại từng bảng dữ liệu trong databasse.

- Chạy thực thi lệnh xoá tablespace của bảng cần khôi phục:

ALTER TABLE <Tên bảng cần khôi phục> DISCARD TABLESPACE

Sau khi chạy lệnh trên trong thư mục Mysql/data/<database mới> sẽ mất file .ibd của bảng bạn đang khôi phục.

- Bạn sao chép file .ibd của bảng trong thư mục của cơ sở dữ liệu bị lỗi vào Mysql/data/<database mới>.

- Chạy thực thi lệnh import lại tablespace của bảng cần khôi phục.

ALTER TABLE <Tên bảng cần khôi phục> IMPORT TABLESPACE

Sau khi chạy lệnh bạn sẽ thấy được dữ liệu của bảng, tới đây là bạn đã khôi phục được một bảng dữ liệu.

Các bạn thực hiện theo bước 2 cho các bảng dữ liệu còn lại là có thể khôi phục lại toàn bộ database của bạn.

Chúc các bạn thành công!

Chia sẻ: Ngụy Kim Hưng