Swift

import Foundation
import CryptoSwift

extension URLSession {
    func synchronousDataTask(with request: URLRequest) -> (Data?, URLResponse?, Error?) {
        var data: Data?
        var response: URLResponse?
        var error: Error?

        let semaphore = DispatchSemaphore(value: 0)

        let dataTask = self.dataTask(with: request) {
            data = $0
            response = $1
            error = $2

            semaphore.signal()
        }
        dataTask.resume()

        _ = semaphore.wait(timeout: .distantFuture)

        return (data, response, error)
    }
}

class RFGAPI {
    private enum Constants {
        static let apiURL = "https://api.researchforgood.com/API"
        static let apid = ""
        static let secretHex = ""
    }

    public func sendTestCommand() {
        let command = "{ \"command\" : \"test/copy/1\" , \"data1\" : \"THIS IS A TEST\"}";
        if let response = send(command: command) {
            print("Received Response: \(response)")
        }
    }

    public func send(command: String) -> String? {
        print("Sending command: \(command)")

        let time = Int(Date().timeIntervalSince1970)

        let packet = "\(time)\(command)"

        let key = Array<UInt8>(hex: Constants.secretHex)

        let bytesCommand = packet.bytes
        do {
            let bytes: [UInt8] = try HMAC(key: key, variant: .sha1).authenticate(bytesCommand)
            let data = Data(bytes: bytes)

            let hashString = data.bytes.toHexString()

            let urlString = "\(Constants.apiURL)?apid=\(Constants.apid)&time=\(time)&hash=\(hashString)"
            guard let url = URL(string: urlString) else {
                print("Error: Cannot generate URL from string. Bailing...")
                return nil
            }

            let urlSession = URLSession(configuration: URLSessionConfiguration.default)
            var request = URLRequest(url: url)
            request.httpMethod = "POST"
            request.addValue("application/json", forHTTPHeaderField: "Content-Type")
            request.addValue("\(command.count)", forHTTPHeaderField: "Content-Length")
            request.httpBody = command.data(using: .utf8)

            let (_responseData, _, error) = urlSession.synchronousDataTask(with: request)
            if let error = error {
                print("Error: \(error)")
                return nil
            }
            guard let responseData = _responseData  else {
                print("Error: Could not receive data.")
                return nil
            }
            if let responseString = String(data: responseData, encoding: .utf8) {
                return responseString
            } else {
                print("Decoding to string failed.")
                return nil
            }
        } catch {
            print("Could not hash: \(error)")
            return nil
        }
    }
}

Download the complete Swift example here.