I implemented a simple IoT Edge module from scratch as simulated temperature and humidity sensor.
When I try to see the messages being sent to the cloud, I receive this error:
SendEventAsync for a named output is available for Modules only.
This is my code:
private static async Task SendMessages(DeviceClient deviceClient)
{
Console.WriteLine("Device sending {0} messages to IoTHub...\n", MessageCount);
var rnd = new Random();
for (var count = 0; count < MessageCount; count++)
{
_temperature = rnd.Next(20, 35);
_humidity = rnd.Next(60, 80);
var alert = _temperature > TemperatureThreshold ? "true" : "false";
var messageBody = new MessageBody
{
DeviceId = ModuleId,
MessageId = count,
Temperature = _temperature,
Humidity = _humidity
};
var dataBuffer = JsonConvert.SerializeObject(messageBody);
var eventMessage = new Message(Encoding.UTF8.GetBytes(dataBuffer));
eventMessage.Properties.Add("temperatureAlert", alert);
Console.WriteLine("\t{0}> Sending message: {1}, Data: [{2}]", DateTime.Now.ToLocalTime(), count, dataBuffer);
await deviceClient.SendEventAsync("toFilterModule", eventMessage);
}
}
This is my cinnection string:
var connectionString = Environment.GetEnvironmentVariable("EdgeHubConnectionString");
Any idea of how to fix it?
Thank you!
Related
I'd like to peek all messages from several Azure Service Bus queues. After that I want to filter them after queueName, insertDate and give the opportunity to make a full text search on the body.
Currently, I'm using the Microsoft.Azure.ServiceBus package to create a ManagementClient for gathering queue information and then use a MessageReceiver to peek the messages.
var managementClient = new ManagementClient(connectionString);
var queue = await managementClient.GetQueueRuntimeInfoAsync(queueName);
var count = queue.MessageCount;
var receiver = new MessageReceiver(connectionString, queueName);
var messagesOfQueue = new List<Message>();
for (var i = 1; i <= count; i++)
{
messagesOfQueue.Add(await receiver.PeekAsync());
}
Is there a better way to get all messages? Or is there even a way to only peek messages that apply to a filter?
I've also tried to use the QueueClient.PeekBatch Method from the WindowsAzure.ServiceBus package. But that method didn't return all messages although I've set the correct messageCount parameter.
And then there is also the package Azure.Messaging.ServiceBus... What's up with all these packages?
So which of the packages should I use and what is the best way for peeking messages of queues based on some filters?
The solution I'm currently using and which works as expected looks like this:
var receiver = serviceBusClient.CreateReceiver(queueName);
var messagesOfQueue = new List<ServiceBusReceivedMessage>();
var previousSequenceNumber = -1L;
var sequenceNumber = 0L;
do
{
var messageBatch = await receiver.PeekMessagesAsync(int.MaxValue, sequenceNumber);
if (messageBatch.Count > 0)
{
sequenceNumber = messageBatch[^1].SequenceNumber;
if (sequenceNumber == previousSequenceNumber)
break;
messagesOfQueue.AddRange(messageBatch);
previousSequenceNumber = sequenceNumber;
}
else
{
break;
}
} while (true);
It uses the nuget package Azure.Messaging.ServiceBus.
Currently you're receiving a single message from the receiver. A better option would be to receive messages in batch using PeekBatchAsync(Int64, Int32) method of MessageReceiver.
Here's the sample code to do so (untested though):
var messagesOfQueue = new List<Message>();
var sequenceNumber = 0;
var batchSize = 100;//number of messages to receive in a single call
do
{
var messages = await receiver.PeekBatchAsync(sequenceNumber, batchSize);
messagesOfQueue.AddRange(messages);
if (messages.Count > 0)
{
sequenceNumber = messages[messages.Count-1].SequenceNumber;
}
else
{
break;
}
} while (true);
The solution avoids getting the message with the same SequenceNumber twice.
Sequence numbers monotonically increase. And I've tested most cases except rolling over sequenceNumber to 0 when it reaches the maximum value (Long.MaxValue).
using Azure.Messaging.ServiceBus;
private static async Task<List<ServiceBusReceivedMessage>> PeekAllMessages(string serviceBusConnectionString, string queueName)
{
var client = new ServiceBusClient(serviceBusConnectionString);
var receiver = client.CreateReceiver(queueName);
var messages = new List<ServiceBusReceivedMessage>();
var batchSize = 20;
var sequenceNumber = 0L;
do
{
var messageBatch = await receiver.PeekMessagesAsync(batchSize, sequenceNumber);
if (messageBatch.Count <= 0)
{
break;
}
// Increasing the SequenceNumber by 1 to avoid getting the message with the same SequenceNumber twice
sequenceNumber = messageBatch[^1].SequenceNumber + 1;
messages.AddRange(messageBatch);
} while (true);
return messages;
}
I am trying to delete message in SQS queue, but it is not deleting in the queue. I have been trying to make a lot of changes, but is still not working. I am new to c#, .net core, and AWS. Can anyone please help me with this?
Here is my main method:
[HttpGet]
public async Task<ReceiveMessageResponse> Get()
{
ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest
{
WaitTimeSeconds = 3 //it'll ping the queue for 3 seconds if I don't do this, sometimes I receive message and sometimes I don't
};
receiveMessageRequest.QueueUrl = myQueueUrl;
receiveMessageRequest.MaxNumberOfMessages = 10; // can change number of messages as needed
//receiveing messages/responses
var receiveMessageResponse = await amazonSQSClient.ReceiveMessageAsync(receiveMessageRequest);
if (receiveMessageResponse.Messages.Count > 0){
var bucketName = getBucketName(receiveMessageResponse);
var objectKey = getObjectKey(receiveMessageResponse);
var versionId = getVersionId(receiveMessageResponse);
string filePath = "C:\\InputPdfFile\\"; // change it later
string path = filePath + objectKey;
//get the file from s3 bucket and download it in in
var downloadInputFile = await DownloadAsync(path, versionId, objectKey);
//Get score from the output file
string jsonOutputFileName = "\\file-1.txt"; //change it later from text file to json file
string jsonOutputPath = "C:\\OutputJsonFile"; //change it later
string jasonArchivePath = "C:\\ArchiveJsonFile"; //change it later
int score = GetOutputScore(jsonOutputPath, jsonOutputFileName);
//update metadata from the score received from ML worker (GetOutputScore)
PutObjectResponse putObjectResponse = await UpdateMetadataAsync(score);
//Move file from output to archive after updating metadata
string sourceFile = jsonOutputPath + jsonOutputFileName;
string destFile = jasonArchivePath + jsonOutputFileName;
if (!Directory.Exists(jasonArchivePath))
{
Directory.CreateDirectory(jasonArchivePath);
}
System.IO.File.Move(sourceFile, destFile);
//delete message after moving file from archive
*DeleteMessage(receiveMessageResponse);* //not sure why it is not deleting**
}
return receiveMessageResponse;
}
Here is my Delete method:
public async void DeleteMessage(ReceiveMessageResponse receiveMessageResponse)
{
if (receiveMessageResponse.Messages.Count > 0)
{
foreach (var message in receiveMessageResponse.Messages)
{
var delRequest = new DeleteMessageRequest
{
QueueUrl = myQueueUrl,
ReceiptHandle = message.ReceiptHandle
};
var deleteMessage = await amazonSQSClient.DeleteMessageAsync(delRequest);
}
}
else // It is not going in else because the message was found but still not deleting it
{
Console.WriteLine("No message found");
}
}
Any help would be greatly appreciated!
I am running on TestNet. I am trying to add multiple transaction inputs TxIn() so as to spend from these inputs. When I broadcast my transaction, it returns successful but I can't see it on the block-explorer. I have handled a transaction with a single TxIn() and when I broadcast it, it was successful and i could view it on the block-explorer. I have been on this for more than 2 days now. Will greatly appreciate your help guys
var bitcoinPrivateKey = new BitcoinSecret("cNZupUgfs54DmsShwxa1wpomQcszUtuJYFvx9zWPbXrT7KsWtiUd");
var network = bitcoinPrivateKey.Network;
var address = bitcoinPrivateKey.GetAddress();
var client = new QBitNinjaClient(network);
var balance = client.GetBalance(address).Result;
var transactionId = uint256.Parse("06c0aec7543467951abad0c28998a2c1fc1cdc34e01113f8ec1fdb22be854771");
var transactionResponse = client.GetTransaction(transactionId).Result;
var tx = new Transaction();
foreach (var operation in balance.Operations)
{
OutPoint spendOutPoint = null;
var coinsReceived = operation.ReceivedCoins;
foreach (var coin in coinsReceived)
{
if (coin.TxOut.ScriptPubKey == bitcoinPrivateKey.ScriptPubKey)
{
spendOutPoint = coin.Outpoint;
tx.Inputs.Add(new TxIn()
{
PrevOut = spendOutPoint
});
}
}
}
var chimaTestDestinationAddress = new BitcoinPubKeyAddress("mxgN2AiqHjKfGvo6Y57fAe4Y754rPdKf4P");
TxOut chimaTestDestinationAddressTxOut = new TxOut()
{
Value = new Money((decimal)0.50, MoneyUnit.BTC),
ScriptPubKey = chimaTestDestinationAddress.ScriptPubKey
};
TxOut ugoChangeBackTxOut = new TxOut()
{
Value = new Money((decimal)2.98, MoneyUnit.BTC),
ScriptPubKey = bitcoinPrivateKey.ScriptPubKey
};
tx.Outputs.Add(chimaTestDestinationAddressTxOut);
tx.Outputs.Add(ugoChangeBackTxOut);
var msg = "ugo the jedi master";
var msgBytes = Encoding.UTF8.GetBytes(msg);
TxOut txDesc = new TxOut()
{
Value = Money.Zero,
ScriptPubKey = TxNullDataTemplate.Instance.GenerateScriptPubKey(msgBytes)
};
tx.Outputs.Add(txDesc);
tx.Inputs[0].ScriptSig = bitcoinPrivateKey.PubKey.WitHash.ScriptPubKey;
tx.Inputs[1].ScriptSig = bitcoinPrivateKey.PubKey.WitHash.ScriptPubKey;
tx.Inputs[2].ScriptSig = bitcoinPrivateKey.PubKey.WitHash.ScriptPubKey;
tx.Inputs[3].ScriptSig = bitcoinPrivateKey.PubKey.WitHash.ScriptPubKey;
tx.Inputs[4].ScriptSig = bitcoinPrivateKey.PubKey.WitHash.ScriptPubKey;
tx.Sign(bitcoinPrivateKey, false);
BroadcastResponse broadcast = client.Broadcast(tx).Result;
if (!broadcast.Success)
{
Console.WriteLine("ErrorCode: " + broadcast.Error.ErrorCode);
Console.WriteLine("Error message: " + broadcast.Error.Reason);
}
else
{
Console.WriteLine("Success, you can now checkout the transaction in any block explorer");
Console.WriteLine("Hash: " + tx.GetHash());
}
I am trying to write some c# script to write some data to celery queue that has been already created by my celery app (which I developed in Python). Whenever I try to send data to the celery queue the messages stuck under "Unacked" status, which doesn't happens whenever I write those same messages to another queue.
Here is my c# code that tries to write the messages to the celery queue under rabbitmq:
public static void SendMessages(List < CeleryMessage > celeryMessages, string taskName) {
ConnectionFactory factory = new ConnectionFactory {
HostName = CeleryHostName,
UserName = "guest",
Password = "guest",
VirtualHost = "/"
};
using(IConnection connection = factory.CreateConnection())
using(IModel channel = connection.CreateModel()) {
foreach(CeleryMessage celeryMessage in celeryMessages) {
SendMessageSecondVersion(channel, celeryMessage, taskName);
Console.WriteLine(" [X] Sent {0}", celeryMessage);
}
}
}
private static void SendMessageSecondVersion(IModel channel, CeleryMessage celeryMessage, string taskName) {
var myDict = new Dictionary < string,
string > ();
myDict["id"] = "4cc7438e-afd4-4f8f-a2f3-f46567e7ca77";
myDict["task"] = "celery.task.PingTask";
myDict["args"] = "[]";
myDict["kwargs"] = "{}";
myDict["retries"] = "0";
myDict["eta"] = "2009-11-17T12:30:56.527191";
var result = string.Join(", ", myDict.Select(m => m.Key + ":" + m.Value).ToArray());
var body = Encoding.UTF8.GetBytes(result);
channel.BasicPublish(exchange: "testcelery", routingKey: "testcelery", basicProperties: null, body: body);
}
This is my publisher. There are two consumers. MailConsumer and SmsConsumer.
using(var bus = RabbitHutch.CreateBus("host=localhost").Advanced) {
var queueName = "my.queue";
var queueName2 = "my.queue2";
var queue = bus.QueueDeclare(queueName);
var queue2 = bus.QueueDeclare(queueName2);
var channel = bus.ExchangeDeclare("MyFanout", ExchangeType.Fanout);
bus.Bind(channel, queue, "sms");
bus.Bind(channel, queue2, "mail");
var input = "";
Console.WriteLine("Enter a message. 'q' to quit.");
while((input = Console.ReadLine()) != "q") {
for(int i = 1; i < 2; i++) {
var message = new Message<TextMessage>(new TextMessage {
Text = input + i
});
bus.Publish(channel, "", false, false, message);
}
}
}
I can subscribe with this code:
using(var bus = RabbitHutch.CreateBus("host=localhost").Advanced) {
var queueName = "my.queue2";
var queue = bus.QueueDeclare(queueName);
bus.Consume(queue, x => x.Add<TextMessage>((message, info) => {
Thread.Sleep(1000);
Console.WriteLine("SMS: {0}", message.Body.Text);
}));
Console.WriteLine("Listening for messages. Hit <return> to quit.");
Console.ReadLine();
}
How can I achieve it via AutoSubscriber? There is no option for Queue Name in AutoSubscriber, there is "Subscription Id"
There's a property on the AutoSubscriber called 'GenerateSubscriptionId', which you can set to generate the subscription id for a consumer:
subscriber.GenerateSubscriptionId = subscriptionInfo =>
{
return "MyApplication:" + subscriptionInfo.ConcreteType.Name);
};
Then the subscription id will be used by the default conventions to generate a queue name.
Update:
I think you can achieve what you want just with normal pub-sub without declaring any queue.
In your publisher you can do this:
var bus = RabbitHutch.CreateBus("host=localhost")
while((input = Console.ReadLine()) != "q") {
for(int i = 1; i < 2; i++) {
var message = new Message<TextMessage>(new TextMessage {
Text = input + i
});
bus.Publish(message);
}
}
Then just create 2 consumers to subscribe to your message, and your message will be handled by both:
class SmsConsumer : IConsume<TextMessage>{
...
}
class LogConsumer : IConsume<TextMessage>{
...
}
and in your startup:
var bus = RabbitHutch.CreateBus("host=localhost")
var subscriber = new AutoSubscriber(bus,"my_applications_subscriptionId_prefix");
subscriber.Subscribe(Assembly.GetExecutingAssembly());
Console.ReadLine()
EasyNetQ will declare the exchange, queues and bindings for you. Just make sure your TextMessage class is in an assembly shared by both projects.